题目大意:
小Z在MOI比赛中获得了大奖,奖品是一张特殊的机票。使用这张机票,可以在任意一个国家内的任意城市之间的免费飞行,只有跨国飞行时才会有额外的费用。小Z获得了一张地图,地图上有城市之间的飞机航班和费用。已知从每个城市出发能到达所有城市,两个城市之间可能有不止一个航班。一个国家内的每两个城市之间一定有不止一条飞行路线,而两个国家的城市之间只有一条飞行路线。小Z想知道,从每个城市出发到额外费用最大的城市,以便估算出出行的费用,请你帮助他。当然,你不能通过乘坐多次一个航班增加额外费用,也就是必须沿费用最少的路线飞行。
Solution:
双连通分量缩点后DP求树上每个点出发的最长路。
DP同:http://acm.hdu.edu.cn/showproblem.php?pid=2196
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
const int N=20010;
int n,m,cnt,Bcc_Cnt;
int Low[N],Pre[N];
int Bcc[N],Dfs_t;
stack<int> S;
int Dis[N],SDis[N];
int Num[N],SNum[N];
struct Node
{
int to;
int w;
Node *nxt;
};
Node G[N],H[N];
Node Poor[1000010];
//------------------------------------------
inline void PushNew(int u,int v,int w)
{
Node *t=&Poor[cnt++];
t->to=v;
t->w=w;
t->nxt=G[u].nxt;
G[u].nxt=t;
}
inline void Push(int u,int v,int w)
{
Node *t=&Poor[cnt++];
t->to=v;
t->w=w;
t->nxt=H[u].nxt;
H[u].nxt=t;
}
//------------------------------------------
void Dfs(int u,int f)
{
Low[u]=Pre[u]=++Dfs_t;
S.push(u);
for(Node *i=H[u].nxt;i;i=i->nxt)
{
int v=i->to;
if(v==f)continue;
if(!Pre[v])
{
Dfs(v,u);
Low[u]=min(Low[u],Low[v]);
if(Low[v]>Pre[u])
{
++Bcc_Cnt;
while(1)
{
int t=S.top();
Bcc[t]=Bcc_Cnt;
S.pop();
if(t==v)break;
}
}
}
else
Low[u]=min(Low[u],Pre[v]);
}
}
void Find_Bcc()
{
for(int i=1;i<=n;++i)
if(!Pre[i])
{
while(!S.empty())S.pop();
Dfs(i,-1);
++Bcc_Cnt;
for(int j=1;j<=n;j++)
if(Pre[j] && !Bcc[j])Bcc[j]=Bcc_Cnt;
}
for(int u=1;u<=n;++u)
for(Node *i=H[u].nxt;i;i=i->nxt)
{
int v=i->to;
int x=Bcc[u];
int y=Bcc[v];
if(x==y)continue;
PushNew(x,y,i->w);
}
}
//------------------------------------------
void Dp_Dfs(int u,int f)
{
Dis[u]=SDis[u]=0;
for(Node *i=G[u].nxt;i;i=i->nxt)
{
int v=i->to,w=i->w;
if(v==f)continue;
Dp_Dfs(v,u);
if(SDis[u]<Dis[v]+w)
{
SDis[u]=Dis[v]+w;
SNum[u]=v;
if(SDis[u]>Dis[u])
{
swap(SDis[u],Dis[u]);
swap(SNum[u],Num[u]);
}
}
}
}
void Dp_Dfs2(int u,int f)
{
for(Node *i=G[u].nxt;i;i=i->nxt)
{
int v=i->to,w=i->w;
if(v==f)continue;
Dp_Dfs(v,u);
if(Num[u]==v)
{
if(SDis[v]<SDis[u]+w)
{
SDis[v]=SDis[u]+w;
SNum[v]=u;
if(SDis[v]>Dis[v])
{
swap(SDis[v],Dis[v]);
swap(SNum[v],Num[v]);
}
}
}
else
{
if(SDis[v]<Dis[u]+w)
{
SDis[v]=Dis[u]+w;
SNum[v]=u;
if(SDis[v]>Dis[v])
{
swap(SDis[v],Dis[v]);
swap(SNum[v],Num[v]);
}
}
}
Dp_Dfs2(v,u);
}
}
//------------------------------------------
int main()
{
freopen("freeline.in","r",stdin);
freopen("freeline.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=m;++i)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
Push(a,b,c);
Push(b,a,c);
}
Find_Bcc();
Dp_Dfs(1,-1);
Dp_Dfs2(1,-1);
for(int i=1;i<=n;i++)printf("%d\n",Dis[Bcc[i]]);
return 0;
}