Description
Serpent(水蛇)生活的地方有N个水坑,编号为0,…,N - 1,有M条双向小路连接这些水坑。每两个水坑之间至多有一条路径(路径包含一条或多条小路)相互连接,有些水坑之间根本无法互通(即M ≤ N-1 )。Serpent走过每条小路需要一个固定的天数,不同的小路需要的天数可能不同。Serpent的朋友袋鼠希望新修 N - M - 1条小路,让Serpent可以在任何两个水坑间游走。袋鼠可以在任意两个水坑之间修路,Serpent通过每条新路的时间都是L天。袋鼠希望找到一种修路方式使得修路之后Serpent在每两个水坑之间游走的最长时间最短。
举例说明
上图中有12个水坑8条小路( N = 12, M = 8)。假如L = 2 ,即Serpent通过任何一条新路都需要2天。那么,袋鼠可以修建3条新路:
水坑1和水坑2之间;
水坑1和水坑6之间;
水坑4和水坑10之间。
上图显示了修路后的最终状态。从水坑0走到水坑11的时间最长,需要18天。这是 最佳结果,无论袋鼠如何选择修路方式,总会存在一些水坑对,Serpent需要18天 或者更长时间从其中一个走到另一个。
题解:
首先预处理出每个点的作为起点的最长路和次长路,然后根据这个就可以求出每棵树哪个点的最长路最短,那么若其它树与这棵树相连,就连这个点(这个显然),然后对每棵树的这个点的最长路从大到小排序,然后两两合并(这个自己画画就知道正确性显然了),维护新树的最长路最短路即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=500010;
int n,m;
LL l;
struct Edge{int y,next;LL d;}e[Maxn<<1];
int last[Maxn],len=0;
void ins(int x,int y,LL d){int t=++len;e[t].y=y;e[t].d=d;e[t].next=last[x];last[x]=t;}
LL mx1[Maxn],mx2[Maxn],tmp;
bool vis[Maxn];
int p[Maxn],lp=0,ansp;
int rt;
void dfs1(int x,int fa)
{
mx1[x]=0;vis[x]=true;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa)continue;
dfs1(y,x);
if(e[i].d+mx1[y]>=mx1[x])
{
mx2[x]=mx1[x];
mx1[x]=e[i].d+mx1[y];
}
else if(e[i].d+mx1[y]>mx2[x])mx2[x]=e[i].d+mx1[y];
}
}
LL ans=0;
void dfs2(int x,int fa,LL d)
{
LL tot=0;
if(fa)
{
if(mx1[fa]==d+mx1[x])
{
if(mx2[fa]+d>=mx1[x])
{
mx2[x]=mx1[x];
mx1[x]=mx2[fa]+d;
}
else if(mx2[fa]+d>mx2[x])mx2[x]=mx2[fa]+d;
}
else
{
if(mx1[fa]+d>=mx1[x])
{
mx2[x]=mx1[x];
mx1[x]=mx1[fa]+d;
}
else if(mx1[fa]+d>mx2[x])mx2[x]=mx1[fa]+d;
}
}
if(mx1[x]<tmp)tmp=mx1[x],ansp=x;
ans=max(ans,mx1[x]+mx2[x]);
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa)continue;
dfs2(y,x,e[i].d);
}
}
bool cmp(int x,int y){return mx1[x]>mx1[y];}
int main()
{
scanf("%d%d%lld",&n,&m,&l);
for(int i=1;i<=n;i++)vis[i]=false,mx2[i]=0;
for(int i=1;i<=m;i++)
{
int x,y;LL d;
scanf("%d%d%lld",&x,&y,&d);x++;y++;
ins(x,y,d);ins(y,x,d);
}
for(int i=1;i<=n;i++)
if(!vis[i])
{
tmp=(1LL<<60);
dfs1(i,0);dfs2(i,0,0);
p[++lp]=ansp;
}
sort(p+1,p+1+lp,cmp);
for(int i=2;i<=lp;i++)
{
int t1=p[i-1],t2=p[i];
ans=max(max(mx1[t1]+mx2[t1],mx1[t2]+mx2[t2]),mx1[t1]+mx1[t2]+l);
LL tmp1=mx1[t1];
if(l+mx1[t2]>=mx1[t1])
{
mx2[t1]=mx1[t1];
mx1[t1]=l+mx1[t2];
}
else if(l+mx1[t2]>mx2[t1])mx2[t1]=l+mx1[t2];
if(l+tmp1>=mx1[t2])
{
mx2[t2]=mx1[t2];
mx1[t2]=l+tmp1;
}
else if(l+tmp1>mx2[t2])mx2[t2]=l+tmp1;
if(mx1[t1]<mx1[t2])p[i]=t1;
else p[i]=t2;
}
printf("%lld",ans);
}