题目背景
冴月麟和魏潇承是好朋友。
题目描述
冴月麟为了守护幻想乡,而制造了幻想乡的倒影,将真实的幻想乡封印了。任何人都无法进入真实的幻想乡了,但是她给前来救她的魏潇承留了一个线索。
她设置了一棵树(有根)。树的每一条边上具有割掉该边的代价。
魏潇承需要计算出割开这棵树的最小代价,这就是冴月麟和魏潇承约定的小秘密。
帮帮魏潇承吧。
注:所谓割开一棵有根树,就是删除若干条边,使得任何任何叶子节点和根节点不连通。
输入格式
输入第一行两个整数
n
,
接下来
n−1
行每行三个整数
a
、
输出格式
输出包含一行,一个整数,表示所求最小代价。
输入样例#1
4 1
1 2 1
1 3 1
1 4 1
输出样例#1
3
输入样例#2
4 1
1 2 3
2 3 1
3 4 2
输出样例#2
1
说明
对于20%的数据,
n<=10
对于50%的数据,
n<=1000
对于100%的数据,
n<=100000
思路
洛谷这标程。。。一个字:看不懂(这个好像是三个字吧)。
就说一说我自己的思路吧。
好吧,也没有什么思路可言,这道题就是真·tree dp啊。
那么就上代码吧。
代码
#include <cstdio>
#include <algorithm>
const int maxn=100000;
const int inf=1000000000;
int f[maxn+10],n,root;
int pre[(maxn<<1)+10],now[maxn+10],son[(maxn<<1)+10],tot,val[(maxn<<1)+10];
int ins(int a,int b,int c)
{
tot++;
pre[tot]=now[a];
now[a]=tot;
son[tot]=b;
val[tot]=c;
return 0;
}
int dfs(int u,int fa)
{
int j=now[u],flag=0;
while(j)
{
int v=son[j];
if(v==fa)
{
j=pre[j];
continue;
}
flag=1;
dfs(v,u);
f[u]+=std::min(f[v],val[j]);//状态转移方程
j=pre[j];
}
if(!flag)
{
f[u]=inf;//如果是叶子节点,就打成inf
}
return 0;
}
int main()
{
scanf("%d%d",&n,&root);
for(int i=1; i<n; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
ins(a,b,c);
ins(b,a,c);
}
dfs(root,0);
printf("%d\n",f[root]);
return 0;
}