NOIP模拟——航班

L因为业务繁忙,经常会到处出差。因为他是航空公司的优质客户,于是某个航空公司给了他一个优惠券。
他可以利用这个优惠券在任何一个国家内的任意城市间免费旅行,当他的路线跨国才会产生费用。L有一个航空公司的价格表与航线。而且每个城市出发都能到所有的城市,2个城市间可能有不止一个航班,一个国家内的2个城市间一定有不同的路线,但是不同国家的城市间只有一条路线。L想知道从每个城市出发到产生费用最多的城市,不过你不能重复在一个航班上飞来飞去产生费用,必须沿最少的费用路线飞行
输入
第一行,两个整数 N,M,表示N 个城市, M 条航线。
接下来 M 行,每行三个整数 a,b,c,表示城市 a,b 之间有一条费用为 c 的航线。
输出
共 N 行,第 i 行为从城市 i 出发到达每个城市额外费用的最大值。
样例输入
6 6
1 4 2
1 2 6
2 5 3
2 3 7
6 3 4
3 1 8
样例输出
4
4
4
6
7
7
提示
【解释】
有四个国家,包含的城市分别为 {1,2,3},{4},{5},{6}。
从城市 1 出发到达城市 6,乘坐(1,3)(3,6)两个航班费用最大,(1,3)在国内为免费航班, (3,6)的费用为 4,所以从 1 出发的最大费用为 4。
【数据规模】
对于 40%的数据 1<=N<=1000,1<=M<=1000
对于 100%的数据 1<=N<=20000,1<=M<=200000

还好吧
算比较简单得了
主要是忘了tarjan缩点的写法了

只需要先缩点

缩了点之后注意不能直接最短路什么之类的

要找到图的直径

可以证明对于每个点最远的距离就是它到直径的两个端点的最大值

双重DFS求直径就是了

#include<bits/stdc++.h>
using namespace std;
inline int read(){
 char ch=getchar();
 while(!isdigit(ch)) ch=getchar();
 int res=0;
 while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
 return res;
} 
int n,m,data,dfn[20005],cnt1,low[20005],adj[20005],adj1[20005],nxt[400005],nxt1[400005],cnt,dis[20005],dis1[20005],mx,root,bel[20005],belnum,val[400005],val1[400005],to1[400005],to[400005];
stack<int> stk;
bool vis[20005];
inline void addedge(int u,int v,int w)
{
 nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
 nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,val[cnt]=w;
}
inline void tarjan(int u,int fa)
{
 dfn[u]=low[u]=++data;
 vis[u]=true;
 stk.push(u);
 for(int i=adj[u];i!=-1;i=nxt[i])
 {
  int v=to[i];
  if(!dfn[v])
  {
   tarjan(v,u);
   low[u]=min(low[u],low[v]);
  }
  else if(vis[v]&&v!=fa)
  {
   low[u]=min(low[u],dfn[v]);
  }
 }
 if(dfn[u]==low[u])
 {
  belnum++;
  int tmp;
  do{
   tmp=stk.top();
   bel[tmp]=belnum;
   vis[tmp]=false;
   stk.pop();
  }while(tmp!=u);
 }
}
inline void inpoint(){
 memset(adj,-1,sizeof(adj));
 for(int i=1,u,v,va;i<=m;i++)
 {
  u=read(),v=read(),va=read();
  addedge(u,v,va);
 }
 for(int i=1;i<=n;i++)
 {
  if(!dfn[i]) tarjan(i,0);
  }
}
inline void add(int u,int v,int w)
{
 nxt1[++cnt]=adj1[u],adj1[u]=cnt,to1[cnt]=v,val1[cnt]=w;
}
inline void dfs1(int u,int fa)
{
 for(int i=adj1[u];i!=-1;i=nxt1[i])
 {
  int v=to1[i];
  if(v==fa) continue;
  dis[v]=dis[u]+val1[i];
  if(dis[v]>mx) mx=dis[v],root=v;
  dfs1(v,u);
 }
}
inline void dfs2(int u,int fa)
{
 for(int i=adj1[u];i!=-1;i=nxt1[i])
 {
  int v=to1[i];
  if(v==fa) continue;
  dis1[v]=dis1[u]+val1[i];
  
  dfs2(v,u);
 }
}
inline void finddia(){
 cnt=0;
 memset(adj1,-1,sizeof(adj1));
 for(int i=1;i<=n;i++)
 {
  for(int j=adj[i];j!=-1;j=nxt[j])
  {
   if(bel[i]!=bel[to[j]])
   {
    add(bel[i],bel[to[j]],val[j]);
   }
  }
 }
 dfs1(1,-1);
 mx=0;
 memset(dis,0,sizeof(dis));
 dfs1(root,-1);
 mx=0;
 dfs2(root,-1);
 for(int i=1;i<=n;i++)
 {
  cout<<max(dis[bel[i]],dis1[bel[i]])<<endl;
 }
 
}
int main(){
// freopen("in.cpp","r",stdin);
 memset(adj,-1,sizeof(adj));
 n=read(),m=read();
 inpoint();
 finddia();
}

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/82948061