hdu 3452 Bonsai(树形dp)另一种建树的方式

1、http://acm.hdu.edu.cn/showproblem.php?pid=3452

2、题目大意:

给出一棵无向树,每条边都有权值,已知根节点是r,现在要删除部分边,使得所有的叶子结点都不与根连通,求删掉的这些边的最小权值和是多少?

首先我们要从根节点开始遍历,从子节点更新到父节点,用dp[i]表示以i结点为根的子树保证子节点不连通最小代价和,那么dp[r]即所求

dp[i]+=min(w[i],dp[j]);dp[j]是i的子节点

 if(v[i] != fa)//如果不判断是不是根节点,将导致无线循环,因为边是无向的,例如1是2的父节点,1调用2,2调用1,1再调用2.。。。。。
        {
            flag = 1;
            dfs(v[i], cur);
            dp[cur] += min(w[i], dp[v[i]]);
        }

 

4、用vector存储树会导致栈溢出???参考网上的存储树的方法可AC

注意n=1的情况

5、AC代码:

#include<stdio.h>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 2005
#define INF 0x7fffffff
int dp[N];
int tmp=0;
int  e, next[N], v[N], w[N],adj[N];
void add(int x, int y, int z)
{
    v[e] = y, w[e] = z;
    next[e] = adj[x], adj[x] = e ++;
}
void dfs(int cur, int fa)
{
    int i, flag = 0;
    dp[cur] = 0;
    for(i = adj[cur]; i != -1; i = next[i])
        if(v[i] != fa)
        {
            flag = 1;
            dfs(v[i], cur);
            dp[cur] += min(w[i], dp[v[i]]);
        }
    if(flag == 0) dp[cur] = INF;
}
//这种flag判断错误,求解
//void dfs(int u,int fa)
//{
//    printf("*%d*",u,dp[1]);
//    int i,flag=0;
//    dp[u]=0;
//    for( i=first[u]; i != -1; i = next[i])
//    {
//        flag=1;
//        int vv=v[i];
//        int ww=w[i];
//        if(vv==fa)
//        {
//            flag=0;
//            continue;
//        }
//        dfs(vv,u);
//        printf("&%d& ",vv);
//        dp[u]+=min(ww,dp[vv]);
//        //printf("$%d %d %d$",tmp,ww,dp[vv]);
//    }
//    if(flag==0)
//        dp[u]=INF;
//        printf("%d\n",dp[u]);
//
//}
int main()
{
    int n,r,a,b,c;
    while(scanf("%d%d",&n,&r)!=EOF)
    {
        if(n==0 && r==0)
            break;
        memset(adj,-1,sizeof(adj));
        for(int i=1; i<n; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        for(int i=0; i<=n; i++)
            dp[i]=INF;
        //printf("r=%d\n",r);
        if(n==1)
            printf("0\n");
        else
        {
            e=0;
            dfs(r,-1);
            printf("%d\n",dp[r]);
        }

    }
    return 0;
}


 

栈溢出的代码:

#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
#define N 2005
#define INF 0x7fffffff
struct node
{
    int v;
    int w;
};
vector<node> adj[N];
int dp[N];
int tmp=0;
void dfs(int u,int fa)
{
    //printf("*%d*",u,dp[1]);
    int flag=0;
    dp[u]=0;
    for(int i=0; i<adj[u].size(); i++)
    {
        flag=1;
        int vv=adj[u][i].v;
        int ww=adj[u][i].w;
        if(vv==fa)
        {
            flag=0;
            continue;
        }
        dfs(vv,u);
        //printf("&%d& ",vv);
        dp[u]+=min(ww,dp[vv]);
        //printf("$%d %d %d$",tmp,ww,dp[vv]);
    }
    if(flag==0)
        dp[u]=INF;

}
int main()
{
    int n,r,a,b,c;
    while(scanf("%d%d",&n,&r)!=EOF)
    {
        if(n==0 && r==0)
            break;
        for(int i=1; i<n; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            node tmp;
            tmp.v=b;
            tmp.w=c;
            adj[a].push_back(tmp);
            tmp.v=a;
            tmp.w=c;
            adj[b].push_back(tmp);
        }
        for(int i=0; i<=n; i++)
            dp[i]=INF;
        //printf("r=%d\n",r);
        if(n==1)
            printf("0\n");
        else
        {
            dfs(r,-1);
            printf("%d\n",dp[r]);
        }

    }
    return 0;
}


 

你可能感兴趣的:(hdu 3452 Bonsai(树形dp)另一种建树的方式)