[BZOJ]3246: [Ioi2013]Dreaming 暴力乱搞

来源:互联网 发布:粒子群算法工具箱使用 编辑:程序博客网 时间:2024/05/21 13:58

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);}
原创粉丝点击