首页 > 代码库 > bzoj 3246 [Ioi2013] Dreaming 题解
bzoj 3246 [Ioi2013] Dreaming 题解
【原题】
3246: [Ioi2013]Dreaming
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 194 Solved: 68
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天 或者更长时间从其中一个走到另一个。
Input
N : 水坑的数目。
M : 原本存在的小路的数目。
L : Serpent通过新修的路经的时间。
A, B 和 T: 三个包含M个元素的数组,分别表示每条小路的两个端点和通过这条小路的时间。例如,第i条小路连接水坑 A[i-1]和水坑B[i-1],通过这条小路的时间是T[i-1]天。
Output
如上所述,表示游走于两个距离最远的水坑之间所需的时间。
Sample Input
0 8 4
8 2 2
2 7 4
5 11 3
5 1 7
1 3 1
1 9 5
10 6 3
Sample Output
【分析】话说此题坑了我一上午。许昊然的题解已经讲得很详细了。
②我们不妨设每棵树求出来的S的最大值是D[i],最小值是E[i]。显然,我们应该摆成以上形式,使得E[i]最大的在上面。我们再设底下的的E[I]是降序排序的,分别标为E[1],E[2],E[3]。。。那么ans=max(max1+max2+L,max2+max3+2*L)。
③细节很坑。我们要把ans与每一个D[i]求max。别忘了再特判只有1个或2个的情况。
【代码】
#include<cstdio> #include<algorithm> #define N 500005 using namespace std; struct arr{int go,next,s;}a[N*2]; int f[N],Max[N],Maxx[N],temp[N],D[N],E[N],end[N],G[N]; int num,p,i,x,y,z,n,m,L,ans,cnt,Cnt,max1,max2,max3; void add(int u,int v,int w) { a[++cnt].go=v;a[cnt].next=end[u];a[cnt].s=w;end[u]=cnt; } int get(int u){return (f[u]==u)?u:f[u]=get(f[u]);} void Union(int u,int v) { int uu=get(u),vv=get(v); if (uu==vv) return;f[vv]=uu; } void Get(int k,int fa) { for (int i=end[k];i;i=a[i].next) { int go=a[i].go;if (go==fa) continue; Get(go,k); if (Max[go]+a[i].s>Max[k]) Max[k]=Max[go]+a[i].s,temp[k]=go; } for (int i=end[k];i;i=a[i].next) { int go=a[i].go; if (go!=fa&&Max[go]+a[i].s>Maxx[k]&&temp[k]!=go) Maxx[k]=Max[go]+a[i].s; } } void Dfs(int k,int fa) { for (int i=end[k];i;i=a[i].next) { int go=a[i].go;if (go==fa) continue; G[go]=max(G[k],(temp[k]==go)?Maxx[k]:Max[k])+a[i].s; int now=max(Max[go],G[go]); if (now>D[p]) D[p]=now; if (now<E[p]) E[p]=now; Dfs(go,k); } } int main() { scanf("%d%d%d",&n,&m,&L); for (i=1;i<=n;i++) f[i]=i; for (i=1;i<=m;i++) scanf("%d%d%d",&x,&y,&z),add(++x,++y,z),add(y,x,z),Union(x,y); for (p=1;p<=n;p++) if (f[p]==p) { Get(p,0);G[p]=0;D[p]=E[p]=Max[p]; Dfs(p,0);ans=max(ans,D[p]); if (E[p]>max1) {max3=max2;max2=max1;max1=E[p];} else if (E[p]>max2) {max3=max2;max2=E[p];} else if (E[p]>max3) max3=E[p]; Cnt++; } if (Cnt>1) ans=max(ans,max1+max2+L); if (Cnt>2) ans=max(ans,max2+max3+2*L); printf("%d",ans); return 0; }