hdu 5758 Explorer Bo(树形dp)
题目链接:hdu 5758 Explorer Bo
题意:
给一棵n个点的树,每次任选两个点,然后覆盖两点间的所有边,要求以最少的次数覆盖所有的边,在保证次数最少的情况下要求覆盖边的总次数最小
题解:
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 const int N=1e5+7; 6 int t,n,x,y,sz[N],dep[N],mx,ans,in[N],root; 7 vector<int>g[N]; 8 9 void dfs(int x,int fa) 10 { 11 sz[x]=0,dep[x]=dep[fa]+1; 12 for(int &it:g[x])if(it!=fa) 13 dfs(it,x),sz[x]+=sz[it]; 14 if(sz[x]==0)sz[x]=1; 15 if(sz[x]&1)ans++;else ans+=2; 16 } 17 18 void dfs2(int x,int fa,int res=0) 19 { 20 mx=max(mx,res); 21 for(int &it:g[x])if(it!=fa) 22 dfs2(it,x,res+(sz[it]&1?-1:1)); 23 } 24 25 int main(){ 26 scanf("%d",&t); 27 while(t--) 28 { 29 scanf("%d",&n),mx=0,ans=0; 30 F(i,1,n)g[i].clear(),in[i]=0; 31 F(i,2,n) 32 { 33 scanf("%d%d",&x,&y); 34 in[x]++,in[y]++; 35 g[x].push_back(y); 36 g[y].push_back(x); 37 } 38 root=1; 39 F(i,1,n)if(in[i]==1){root=i;break;} 40 dfs(root,0); 41 if(sz[root]&1)ans--;else ans-=2; 42 sz[root]++,dfs2(root,0); 43 if(sz[root]&1)ans-=mx; 44 printf("%d\n",ans); 45 } 46 return 0; 47 }