Tree
Time Limit: 1000ms
Memory Limit: 30000KB
This problem will be judged on PKU. Original ID: 184864-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:
N
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.
N
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 ",dp[1][0] >= INF?-1:dp[1][0]); 41 } 42 return 0; 43 }