POJ 1848 Tree

Tree

Time Limit: 1000ms
Memory Limit: 30000KB
This problem will be judged on PKU. Original ID: 1848
64-bit integer IO format: %lld      Java class name: Main
 
Consider a tree with N vertices, numbered from 1 to N. Add, if it is possible, a minimum number of edges thus every vertex belongs to exactly one cycle.
 

Input

The input has the following structure: 

x(1) y(1) 
x(2) y(2) 
... 
x(N-1) y(n-1) 
N (3 <= N <=100) is the number of vertices. x(i) and y(i) (x(i), y(i) are integers, 1 <= x(i), y(i) <= N) represent the two vertices connected by the i-th edge. 
 

Output

The output will contain the value -1 if the problem doesn't have a solution, otherwise an integer, representing the number of added edges.
 

Sample Input

7
1 2
1 3
3 5
3 4
5 6
5 7

Sample Output

2

Source

 
解题:树形dp
 

本题有三种状态,分别是
dp[u][0],以u为根,所有的点都在环内
dp[u][1],以u为根,除了u外其余的都在环内
dp[u][2],以u为根,除了u和与u点相连的链(至少有两个点)外,其余的点都在环内
有四种状态转移
1、所有子节点都满足在环内,只有根节点不在环内,
dp[u][1]=min(INF,sum);(sum是所有的dp[v][0]的和)
2、有一个子节点不在环内,以该子节点有一条链,将此链连到以u为根的树上,(+1)就可以使得u的所有子节点都在环内
dp[u][0]=min(dp[u][0],sum-dp[v][0]+dp[v][2]+1);
3、有一个子节点不在环内,其余自己处理,
dp[u][2]=min(dp[u][2],sum-dp[v][0]+min(dp[v][1],dp[v][2]));
4、有两个不在环内,将这两个加一条边连起来就可使得所有都在环内
dp[u][0]=min(dp[u][0],sum-dp[v][0]-dp[k][0]+min(dp[v][1],dp[v][2])+min(dp[k][1],dp[k][2])+1);

 

看来别人的解释,还是很好理解的

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 const int INF = 10010;
 7 const int maxn = 200;
 8 vector<int>g[maxn];
 9 int dp[maxn][3];
10 void dfs(int u,int fa){
11     int sum = 0;
12     dp[u][0] = dp[u][1] = dp[u][2] = INF;
13     for(int i = g[u].size()-1; i >= 0; --i){
14         if(g[u][i] == fa) continue;
15         dfs(g[u][i],u);
16         sum += dp[g[u][i]][0];
17     }
18     dp[u][1] = sum;
19     for(int i = g[u].size()-1; i >= 0; --i){
20         if(g[u][i] == fa) continue;
21         dp[u][0] = min(dp[u][0],sum - dp[g[u][i]][0] + dp[g[u][i]][2] + 1);
22         dp[u][2] = min(dp[u][2],sum - dp[g[u][i]][0] + min(dp[g[u][i]][1],dp[g[u][i]][2]));
23         for(int j = g[u].size()-1; j >= 0; --j){
24             if(g[u][j] != g[u][i] && g[u][j] != fa)
25                 dp[u][0] = min(dp[u][0],sum - dp[g[u][i]][0] - dp[g[u][j]][0]
26                                + min(dp[g[u][i]][1],dp[g[u][i]][2]) + min(dp[g[u][j]][1],dp[g[u][j]][2]) + 1);
27         }
28     }
29 }
30 int main(){
31     int n,u,v;
32     while(~scanf("%d",&n)){
33         for(int i = 0; i < maxn; ++i) g[i].clear();
34         for(int i = 1; i < n; ++i){
35             scanf("%d%d",&u,&v);
36             g[u].push_back(v);
37             g[v].push_back(u);
38         }
39         dfs(1,-1);
40         printf("%d\n",dp[1][0] >= INF?-1:dp[1][0]);
41     }
42     return 0;
43 }
View Code

 

posted @ 2015-09-11 09:46  狂徒归来  阅读(250)  评论(0编辑  收藏  举报