http://acm.hdu.edu.cn/showproblem.php?pid=4679
f[u],g[u],k[u]:分别代表u延伸出去的最长边长,第二长边长,第三长边长;
ff[u]:f[u]对应的子节点
gg[u]:g[u]对应的子节点
h[u]:沿着u的父节点方向的最长边
dp[u][0]:以u的所有子节点为根的子树中的子树的直径最大值
dp[u][1]:以u的所有子节点为根的子树中的子树的直径次大值
flag[u]:dp[u][0]对应的u的子节点
ddp[u]:除以u为根的子树外的子树的直径
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; const int maxn = 100100; int f[maxn] , g[maxn] , gg[maxn] , ff[maxn] , k[maxn] , h[maxn] , p[maxn]; struct Edge { int v , w , next ,id; Edge () {} Edge (int v,int w,int next) : v(v) , w(w) , next(next) {}; }edge[maxn<<1]; int E, head[maxn] , n; void init() { E = 0; memset(head,-1,sizeof(int)*(n+1)); } void addedge(int u,int v,int w) { edge[E] = Edge(v ,w, head[u]); head[u] = E++; edge[E] = Edge(u , w, head[v]); head[v] = E++; } queue <int> q; bool vis[maxn]; int sta[maxn] , top; void bfs() { while(!q.empty()) q.pop(); for(int i=1;i<=n;i++) vis[i] = false; q.push(1); p[1] = -1; top = 0; sta[++top] = 1; int u; vis[1] = true; while(!q.empty()) { u = q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(!vis[v]) { p[v] = u; q.push(v); vis[v] = true; sta[++top] = v; } } } } void after_bfs() { //printf("top number is %d\n" , top); while(top > 0) { int u = sta[top--]; vis[u] = false; f[u] = g[u] = gg[u] = 0; ff[u] = -1; for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(v == p[u]) continue; if(f[v] + 1 > f[u]) { f[u] = f[v] + 1; ff[u] = v; } } for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(v == p[u]) continue; if(v == ff[u]) continue; if(f[v] + 1 > g[u]) { g[u] = f[v] + 1; gg[u] = v; } } for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(v == p[u]) continue; if(v == ff[u]) continue; if(v == gg[u]) continue; if(f[v] + 1 > k[u]) { k[u] = f[v] + 1; } } } } void after_bfs2() { h[1] = 0; for(int uu=2;uu<=n;uu++) { int u = sta[uu]; int pa = p[u]; if(ff[pa] == u) { h[u] = max(h[pa]+1 , g[pa]+1); } else { h[u] = max(h[pa]+1 , f[pa]+1); } } } int dp[maxn][2] , flag[maxn]; void after_bfs3() { int top = n; int u; for(int i=1;i<=n;i++) flag[i] = -1 , dp[i][0] = dp[i][1] = 0; while(top > 0) { u = sta[top--]; for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(v == p[u]) continue; int tmp = max(f[v]+g[v],dp[v][0]); if(tmp > dp[u][0]) { dp[u][0] = tmp; flag[u] = v; } } for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(v == p[u] || v == flag[u]) continue; int tmp = max(f[v]+g[v],dp[v][0]); if(tmp > dp[u][1]) { dp[u][1] = tmp; } } } } int ddp[maxn]; void after_bfs4() { for(int i=1;i<=n;i++) ddp[i] = h[i]; for(int uu=2;uu<=n;uu++) { int u = sta[uu]; int papa = p[u]; if(u == flag[papa]) { ddp[u] = max(ddp[u] , dp[papa][1]); } else { ddp[u] = max(ddp[u] , dp[papa][0]); } if(u == ff[papa]) { ddp[u] = max(ddp[u] , g[papa]+k[papa]); } else if(u == gg[papa]) { ddp[u] = max(ddp[u] , f[papa]+k[papa]); } else ddp[u] = max(ddp[u] , f[papa]+g[papa]); } } int ans; void solve() { bfs(); after_bfs(); after_bfs2(); after_bfs3(); after_bfs4(); ans = (1<<29); int tm = -1; for(int u=1;u<=n;u++) { for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].v; if(v == p[u]) continue; int t1 = max(f[v]+g[v] , dp[v][0]); int t2 = 0; if(v == ff[u]) t2 = max(h[u] + g[u] , g[u]+k[u]); else if(v == gg[u]) t2 = max(h[u]+g[u] , f[u]+k[u]); else t2 = max(h[u]+g[u] , f[u]+g[u]); if(v == flag[u]) { t2 = max(t2 , dp[u][1]); } else t2 = max(t2 , dp[u][0]); t2 = max(t2 , ddp[u]); //printf("%d and %d 's detail:\n",u,v); //printf("t1 is %d\n" , t1); //printf("t2 is %d\n" , t2); //puts(""); int tt = max(t1 , t2); if(ans > tt * edge[i].w || ans == tt*edge[i].w && tm > edge[i].id) { ans = tt*edge[i].w; tm = edge[i].id; } } } printf("%d\n" , tm); } void debug() { for(int i=1;i<=n;i++) { printf("the details of no.%d is\n" , i); //printf("f is %d\n" , f[i]); //printf("g is %d\n" , g[i]); //printf("k is %d\n" , k[i]); printf("h is %d\n" , h[i]); //printf("dp[i][0] is %d\n" , dp[i][0]); //printf("dp[i][1] is %d\n" , dp[i][1]); //printf("ddp is %d\n" , ddp[i]); } } void debug2() { for(int i=1;i<=n;i++) { printf("the father of %d is %d\n" , i , p[i]); } } void debug3() { for(int i=0;i<E;i++) printf("i %d\n" , edge[i].id); } int main() { int cas = 1 , T; scanf("%d" , &T); while(T--) { scanf("%d" , &n); init(); for(int i=1;i<n;i++) { int u , v , w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); edge[E-1].id = edge[E-2].id = i; } printf("Case #%d: " , cas++); solve(); //debug3(); } return 0; }