zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    sql server 获取本月的始末时间
    超时时间已到
    sql server定时自动备份
    创建连接服务器
    date制作电子时钟
    C#继承(三)
    C# Split分割
    Dom动态添加属性
    date制作电子时钟(二)
    全局遮罩 shade
  • 原文地址:https://www.cnblogs.com/tobec/p/3260855.html
Copyright © 2011-2022 走看看