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;
}