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();
}