hdu 4679 Terrorist’s destroy 树形DP

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
" , 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:
",u,v);
            //printf("t1 is %d
" , t1);
            //printf("t2 is %d
" , 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
" , tm);
}
void debug() {
    for(int i=1;i<=n;i++) {
        printf("the details of no.%d is
" , i);
        //printf("f is %d
" , f[i]);
        //printf("g is %d
" , g[i]);
        //printf("k is %d
" , k[i]);
        printf("h is %d
" , h[i]);
        //printf("dp[i][0] is %d
" , dp[i][0]);
        //printf("dp[i][1] is %d
" , dp[i][1]);
        //printf("ddp is %d
" , ddp[i]);
    }
}
void debug2() {
    for(int i=1;i<=n;i++) {
        printf("the father of %d is %d
" , i , p[i]);
    }
}
void debug3() {
    for(int i=0;i<E;i++) printf("i   %d
" , 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;
}
原文地址:https://www.cnblogs.com/tobec/p/3260855.html