Tree2cycle HDU - 4714 (NO)

原题链接

考察:树形dp

本蒟蒻是完全没思路,看了网上的题解思路普遍是:

       对于一棵树,每拆掉一条边就形成一条链.对于一个有多子节点的结点u,我们可以保留父节点到u的边和u到一个子节点的边.也可以保留两个子节点的边去掉其他的边.看了大部分题解都是默认去掉父节点边是最优解.

       本蒟蒻是没想出来证明 = =

        思考了一下,不考虑怎么删边的话,遇到多叉点就ans+ =分支数-1.只保留一条边,这是确保该点在一条链上的情况.如果是根节点,就可以保留两条边,这样才能是一条链上.

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cstdio>
 5 using namespace std;
 6 const int N = 1000010;
 7 int h[N],n,idx,ans;
 8 struct Road{
 9     int ne,to;
10 }road[N*2];
11 void inits()
12 {
13     memset(h,-1,sizeof h); idx = 0; ans = 0;
14 }
15 void add(int a,int b)
16 {
17     road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
18 }
19 int dfs(int u,int fa)
20 {
21     int cnt = 0;
22     for(int i=h[u];i!=-1;i=road[i].ne)
23     {
24         int v = road[i].to;
25         if(v==fa) continue;
26         cnt += dfs(v,u);
27     }
28     if(cnt>1)
29     {
30         ans += (cnt-1);
31         if(u==1) ans--; 
32         return 0;
33     }
34     return 1;
35 }
36 int main()
37 {
38     int T;
39     scanf("%d",&T);
40     while(T--)
41     {
42         scanf("%d",&n);
43         inits();
44         for(int i=1;i<n;i++)
45         {
46             int u,v; scanf("%d%d",&u,&v);
47             add(u,v); add(v,u);
48         }
49         dfs(1,-1);
50         printf("%d\n",ans*2+1);
51     }
52     return 0;
53 }

 

posted @ 2021-02-17 01:22  acmloser  阅读(21)  评论(0编辑  收藏  举报