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 }