HDU-4714-贪心
Tree2cycle
Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 3091 Accepted Submission(s): 719
Problem Description
A
tree with N nodes and N-1 edges is given. To connect or disconnect one
edge, we need 1 unit of cost respectively. The nodes are labeled from 1
to N. Your job is to transform the tree to a cycle(without superfluous
edges) using minimal cost.
A cycle of n nodes is defined as follows: (1)a graph with n nodes and n edges (2)the degree of every node is 2 (3) each node can reach every other node with these N edges.
A cycle of n nodes is defined as follows: (1)a graph with n nodes and n edges (2)the degree of every node is 2 (3) each node can reach every other node with these N edges.
Input
The first line contains the number of test cases T( T<=10 ). Following lines are the scenarios of each test case.
In the first line of each test case, there is a single integer N( 3<=N<=1000000 ) - the number of nodes in the tree. The following N-1 lines describe the N-1 edges of the tree. Each line has a pair of integer U, V ( 1<=U,V<=N ), describing a bidirectional edge (U, V).
In the first line of each test case, there is a single integer N( 3<=N<=1000000 ) - the number of nodes in the tree. The following N-1 lines describe the N-1 edges of the tree. Each line has a pair of integer U, V ( 1<=U,V<=N ), describing a bidirectional edge (U, V).
Output
For each test case, please output one integer representing minimal cost to transform the tree to a cycle.
Sample Input
1
4
1 2
2 3
2 4
Sample Output
3
Hint
In the sample above, you can disconnect (2,4) and then connect (1, 4) and
(3, 4), and the total cost is 3.
Source
求将一棵树拆分为一个环的最小的代价,可以拆解边和增加边,代价都是1.
换一下思路,就是把这棵树拆掉det条边形成了det+1条链,再添加det+1条边,总代价就是det*2+1;我们只要求出最小的det就ok了。
对于节点u它可能有一个或多个儿子,如果只有一个儿子的话那就是一条链,不用再管,如果有son个儿子(son>1),我们需要拆掉son-1条边才能保证拆分成链,问题在于应该怎么拆掉这son-1条链才能最优。
fa
|
u
/ | \
v1 v2 v3
对于上面这棵树,我们可以选择拆掉u-v2和u-v3或者是u-fa和u-v1,也就是删掉两个儿子或者一个儿子和一个父亲,会发现后者其实更优,因为避免了父亲形成多儿子的情况,就减少了删除的边数。知道这点就很容易了,递归返回儿子数目即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define inf 0x3f3f3f3f 7 #pragma comment(linker, "/STACK:102400000,102400000") 8 int first[1000010],tot; 9 struct Edge 10 { 11 int v,next; 12 }e[2001000]; 13 void add(int u,int v){ 14 e[tot].v=v; 15 e[tot].next=first[u]; 16 first[u]=tot++; 17 } 18 int aaa; 19 int dfs(int u,int fa) 20 { 21 int s=0; 22 for(int i=first[u];~i;i=e[i].next){ 23 int v=e[i].v; 24 if(v==fa) continue; 25 s+=dfs(v,u); 26 } 27 if(s>1){ 28 aaa+=s-1; 29 if(u==1) aaa--; 30 return 0; 31 } 32 else { 33 return 1; 34 } 35 } 36 int main() 37 { 38 int n,i,j,k,u,v; 39 int t; 40 cin>>t; 41 while(t--){aaa=0; 42 memset(first,-1,sizeof(first)); 43 tot=0; 44 scanf("%d",&n); 45 for(i=1;i<n;++i){ 46 scanf("%d%d",&u,&v); 47 add(u,v); 48 add(v,u); 49 } 50 dfs(1,0); 51 cout<<aaa+aaa+1<<endl; 52 } 53 return 0; 54 }