zoukankan      html  css  js  c++  java
  • hdu 4714 树形DP

    思路:dp[i][0]表示第i个节点为根的子树变成以i为一头的长链最小的花费,dp[i][0]表示表示第i个节点为根的子树变成i不是头的长链最小花费。

    那么动态方程也就不难想了,就是要分几个情况处理,细心就好。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define inf 10000000
    #define Maxn 1100010
    using namespace std;
    int vi[Maxn],head[Maxn],ans,e,dp[Maxn][2];
    struct Edge{
        int u,v,next,val;
    }edge[Maxn*2];
    void init()
    {
        e=0;
        ans=0;
        memset(head,-1,sizeof(head));
        memset(dp,0,sizeof(dp));
        memset(vi,0,sizeof(vi));
    }
    void add(int u,int v)
    {
        edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
        edge[e].v=u,edge[e].u=v,edge[e].next=head[v],head[v]=e++;
    }
    void dfs(int u)
    {
        int i,v;
        vi[u]=1;
        int sum1=0,num1=0,sum2=0,num2=0,sz=0;
        for(i=head[u];i!=-1;i=edge[i].next){
            v=edge[i].v;
            if(vi[v]) continue;
            dfs(v);
            if(dp[v][0]<=dp[v][1]){
                sum1+=dp[v][0];
                num1++;
            }else if(dp[v][0]<=dp[v][1]+1){
                sum2+=dp[v][0];
                num2++;
            }else {
                sum1+=dp[v][1]+2;
            }
            sz++;
        }
        //if(u==1) printf("%d %d %d %d
    ",num1,sum1,num2,sum2);
        if(sz==0) return ;
        if(sz==1){
            dp[u][0]=sum1+sum2;
            dp[u][1]=inf;
            return ;
        }
        if(num1>=1){
            dp[u][0]+=sum1+sum2+num2+(num1-1)*2;
            if(num1>=2){
                dp[u][1]+=sum1+sum2+(num1-2)*2+num2;
            }
            else {
                dp[u][1]+=sum1+sum2+num2;
            }
            return ;
        }
        if(num2>=1){
            dp[u][0]+=sum1+sum2+(num2-1);
            if(num2>=2){
                dp[u][1]+=sum1+sum2+(num2-2);
            }
            else dp[u][1]+=sum1+sum2;
            return ;
        }
        dp[u][0]+=sum1+sum2;
        dp[u][1]+=sum1+sum2;
    }
    int main()
    {
        int t,n,i,j,u,v;
        scanf("%d",&t);
        while(t--){
            init();
            scanf("%d",&n);
            for(i=1;i<n;i++){
                scanf("%d%d",&u,&v);
                add(u,v);
            }
            dfs(1);
            //for(i=1;i<=n;i++)
              //  printf("%d %d %d 
    ",i,dp[i][0],dp[i][1]);
            printf("%d
    ",min(dp[1][0],dp[1][1])+1);
        }
        return 0;
    }
  • 相关阅读:
    高性能TcpServer(Java)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    MySQL连表Update修改数据
    windows服务器安装安全狗时服务名如何填写
    织梦ckeditor编辑器 通过修改js去除img标签内的width和height样式
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3309039.html
Copyright © 2011-2022 走看看