Description
给出N个点,N-1条边的连通图.
现要求删除一条边,使得连通块的直径总和最大.所谓连通块的直径是指连通块中最远两点之间的距离。
问:直径总和最大是多少?
Input
文件名为 delete.in
第一行正整数N.
接下来N-1行.每行两个数,A,B,LEN表示A,B(1<=A,B<=N)有一条长度为Len(1<=Len<=1000)的边连接着.
Output
文件名为 delete.out
一个数Ans.直径总和的最大值.
Sample Input
10 2 1 982 3 1 169 4 1 934 5 1 325 6 1 735 7 1 675 8 2 302 9 3 450 10 5 173
Sample Output
2668
Data Constraint
Hint
【数据范围】
30% N<=100
70% N<=5000
100% N<=100000
题解
- 首先,我们要预处理出每一棵子树的直径和子树中的最远点,次远点和子树中过x的最长链、次长链和次次长链
- 那么考虑删去一条边后直径有哪几种情况
- ①在x的子树里
- ②在x上面的联通块的直径
- ③x子树没被删去的最远点与x上方最远点的和
- ④在x不同子树上最远的点的和
- 那么考虑一下怎么求:
- ①预处理得出
- ②在递归时可以记录当前经过联通块的最大值
- ③x子树里的在预处理里已经求出来,那么不在x子树里的也就是递归经过x的最长链
- ④也就是在x子树里不含被删子树的最远点和次远点
代码
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 struct edge { int to,from,v; }e[100010*2]; 5 int mx[2][100010][4],d[2][100010][4],fa[100010],head[100010],dis[100010],ans,n,cnt; 6 void insert(int x,int y,int z) { e[++cnt].to=y; e[cnt].v=z; e[cnt].from=head[x]; head[x]=cnt; } 7 void dfs(int x) 8 { 9 for (int i=head[x];i;i=e[i].from) 10 { 11 int v=e[i].to; 12 if (v!=fa[x]) 13 { 14 fa[v]=x; 15 dfs(v); 16 dis[x]=max(dis[x],dis[v]); 17 if (dis[v]>mx[0][x][1]) 18 { 19 mx[0][x][2]=mx[0][x][1]; 20 mx[0][x][1]=dis[v]; 21 d[0][x][1]=v; 22 } 23 else if (dis[v]>mx[0][x][2]) mx[0][x][2]=dis[v]; 24 int vis=mx[1][v][1]+e[i].v; 25 if (vis>mx[1][x][1]) 26 { 27 mx[1][x][3]=mx[1][x][2]; 28 mx[1][x][2]=mx[1][x][1]; 29 mx[1][x][1]=vis; 30 d[1][x][2]=d[1][x][1]; 31 d[1][x][1]=v; 32 } 33 else 34 if (vis>mx[1][x][2]) 35 { 36 mx[1][x][3]=mx[1][x][2]; 37 mx[1][x][2]=vis; 38 d[1][x][2]=v; 39 } 40 else if (vis>mx[1][x][3]) mx[1][x][3]=vis; 41 } 42 } 43 dis[x]=max(mx[1][x][1]+mx[1][x][2],mx[0][x][1]); 44 } 45 void find(int x,int a,int b) 46 { 47 int mx1,mx2,mx3; 48 if (x!=1) ans=max(ans,dis[x]+a); 49 for (int i=head[x];i;i=e[i].from) 50 { 51 int v=e[i].to; 52 if (v!=fa[x]) 53 { 54 if (d[1][x][1]==v) 55 { 56 mx1=mx[1][x][2]; 57 mx2=mx[1][x][2]+mx[1][x][3]; 58 } 59 else 60 { 61 mx1=mx[1][x][1]; 62 if (d[1][x][2]==v) mx2=mx[1][x][1]+mx[1][x][3]; else mx2=mx[1][x][1]+mx[1][x][2]; 63 } 64 if (d[0][x][1]==v) mx3=mx[0][x][2]; else mx3=mx[0][x][1]; 65 find(v,max(max(a,mx3),max(mx1+b,mx2)),max(b,mx1)+e[i].v); 66 } 67 } 68 } 69 int main() 70 { 71 scanf("%d",&n); 72 for (int i=1;i<=n-1;i++) 73 { 74 int x,y,z; 75 scanf("%d%d%d",&x,&y,&z); 76 insert(x,y,z); insert(y,x,z); 77 } 78 dfs(1); 79 find(1,0,0); 80 printf("%d",ans); 81 return 0; 82 }
原文地址:https://www.cnblogs.com/Comfortable/p/9281165.html
时间: 2024-09-29 11:07:21