HDU 4714 Tree2cycle DP 2013杭电热身赛 1009
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4714
Tree2cycle
Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 400 Accepted Submission(s): 78
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
题目大意:已知一棵树,切边与连边都需要1的cost。现在要把这棵树分割连接成为一个环,求最小cost。
解题思路:将整棵树拆成N个单枝(所有点的度小于2),所需的cost即为2*N-1(拆成N个单枝需 N-1 cost,合成一个环需要 N cost)。
可用树形DP求出N最小的情况,用dp[i][j]表示以i为根的可用度为j的最小单枝数。
状态转移方程:dp[root][0]=min(dp[root][0]+dp[son][0],dp[root][1]+dp[son][1]-1)
dp[root][1]=min(dp[root][1]+dp[son][0],dp[root][2]+dp[son][1]-1)
dp[root][2]=dp[root][2]+dp[son][0]
P.S. 该题的数据量较大,要加#pragma comment(linker,"/STACK:1024000000,1024000000")语句,而且要用C++编译器,不能用G++。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #pragma comment(linker,"/STACK:1024000000,1024000000") 6 using namespace std; 7 #define N 1000005 8 #define M 2000010 9 int vis[N],all,first[N],next[M],v[M],e,degree[N],dp[N][3]; 10 void addedge(int x,int y) 11 { 12 v[e]=y; 13 next[e]=first[x]; 14 first[x]=e++; 15 } 16 void dfs(int root) 17 { 18 int i,k; 19 dp[root][0]=dp[root][1]=dp[root][2]=1; 20 vis[root]=1; 21 for(i=first[root];i!=-1;i=next[i]) 22 { 23 k=v[i]; 24 if(!vis[k]) 25 { 26 dfs(k); 27 dp[root][0]=min(dp[root][0]+dp[k][0],dp[root][1]+dp[k][1]-1); 28 dp[root][1]=min(dp[root][1]+dp[k][0],dp[root][2]+dp[k][1]-1); 29 dp[root][2]=dp[root][2]+dp[k][0]; 30 } 31 } 32 } 33 int main() 34 { 35 int t,i,x,y; 36 scanf("%d",&t); 37 while(t--) 38 { 39 memset(dp,0,sizeof(dp)); 40 memset(first,-1,sizeof(first)); 41 e=0; 42 all=0; 43 int n; 44 scanf("%d",&n); 45 for(i=1;i<n;i++) 46 { 47 scanf("%d%d",&x,&y); 48 addedge(x,y); 49 addedge(y,x); 50 } 51 memset(vis,0,sizeof(vis)); 52 dfs(1); 53 all=min(dp[1][0],min(dp[1][1],dp[1][2])); 54 // cout<<all<<endl; 55 printf("%d\n",all*2-1); 56 } 57 return 0; 58 }
本人入ACM时间尚短,写的不好的地方请多见谅。