题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3848
题目大意:求一棵树中,距离最短的两个叶节点之间的距离。
思路:树形dp
dp[u][j] 表示以u 为根,摘了j个苹果的最小值!
那么,边界条件为: if(cc[u]==1) dp[u][1]=0;
状态转移方程为:
int tmp=dp[u][1];
dp[u][1]=min(dp[u][1],dp[v][1]+val);
dp[u][2]=min(tmp+dp[v][1]+val,dp[u][2]);
ans=min(ans,dp[u][2]);
ans 即为要求结果!
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=10002;
const int inf=1<<29;
struct node
{
int u,v,val,next;
} Edge[maxn<<2];
int head[maxn],n,dp[maxn][3];
int cc[maxn],NE,ans,vis[maxn];
void addEdge(int u,int v,int val)
{
Edge[NE].u=u;
Edge[NE].v=v;
Edge[NE].val=val;
Edge[NE].next=head[u];
head[u]=NE++;
}
void init()
{
NE=0;
ans=inf;
int i,j;
memset(cc,0,sizeof(cc));
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++)
{
for(j=1;j<=2;j++)
dp[i][j]=inf;
}
}
void dfs(int u,int fa)
{
int i,j,v,val;
if(cc[u]==1) dp[u][1]=0;
for(i=head[u];i!=-1;i=Edge[i].next)
{
v=Edge[i].v;
val=Edge[i].val;
if(v==fa) continue;
dfs(v,u);
int tmp=dp[u][1];
dp[u][1]=min(dp[u][1],dp[v][1]+val);
dp[u][2]=min(tmp+dp[v][1]+val,dp[u][2]);
ans=min(ans,dp[u][2]);
}
}
int main()
{
while(scanf("%d",&n),n)
{
int i,j,u,v,val;
init();
for(i=1; i<n; i++)
{
scanf("%d%d%d",&u,&v,&val);
addEdge(u,v,val);
addEdge(v,u,val);
cc[u]++,cc[v]++;
vis[v]=1;
}
for(i=1; i<=n; i++) if(!vis[i])break;
dfs(i,0);
printf("%d\n",ans);
}
return 0;
}
/*
7
1 2 1
2 3 2
3 4 1
4 5 1
3 6 3
6 7 4
2
1 2 3
5
1 2 2
1 3 3
2 4 1
2 5 4
*/