SAC E#1 - 一道难题 Tree

题目背景

冴月麟和魏潇承是好朋友。

题目描述

冴月麟为了守护幻想乡,而制造了幻想乡的倒影,将真实的幻想乡封印了。任何人都无法进入真实的幻想乡了,但是她给前来救她的魏潇承留了一个线索。

她设置了一棵树(有根)。树的每一条边上具有割掉该边的代价。

魏潇承需要计算出割开这棵树的最小代价,这就是冴月麟和魏潇承约定的小秘密。

帮帮魏潇承吧。

注:所谓割开一棵有根树,就是删除若干条边,使得任何任何叶子节点和根节点不连通。

输入输出格式

输入格式:

输入第一行两个整数n,S表示树的节点个数和根。

接下来n-1行每行三个整数a、b、c,表示a、b之间有一条代价为c的边。

输出格式:

输出包含一行,一个整数,表示所求最小代价。

输入输出样例

输入样例#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

树形dp

令f[x]为切断x与其叶子节点的最小费用

令v=son(x)

如果切割该边的费用小于f[v],那么切这条边就行了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 struct Node
 7 {
 8   int next,to,dis;
 9 }edge[200001];
10 int num,head[100001],f[100001],n,root,ans;
11 void add(int u,int v,int dis)
12 {
13   num++;
14   edge[num].next=head[u];
15   head[u]=num;
16   edge[num].to=v;
17   edge[num].dis=dis;
18 }
19 void dfs(int x,int pa)
20 {int i;
21   for (i=head[x];i;i=edge[i].next)
22     {
23       int v=edge[i].to;
24       if (v!=pa)
25     {
26       dfs(v,x);
27       f[x]+=min(f[v],edge[i].dis);
28     }
29     }
30   if (f[x]==0) f[x]=2e9;
31 }
32 int main()
33 {int i,a,b,c;
34   cin>>n>>root;
35   for (i=1;i<=n-1;i++)
36     {
37       scanf("%d%d%d",&a,&b,&c);
38       add(a,b,c);
39       add(b,a,c);
40     }
41   dfs(root,0);
42   ans=f[root];
43   cout<<ans;
44 }

 

posted @ 2017-10-07 20:42  Z-Y-Y-S  阅读(253)  评论(0编辑  收藏  举报