[dfs][樹的直徑] Jzoj P1737 刪邊
阿新 • • 發佈:2018-07-08
ret desc sam void truct turn scanf 情況 insert
題解
- 首先,我們要預處理出每一棵子樹的直徑和子樹中的最遠點,次遠點和子樹中過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 }
[dfs][樹的直徑] Jzoj P1737 刪邊