題意:給你一棵樹,讓你切掉儘量多的邊,使得產生的全部連通塊都有偶數個結點。spa
對於一棵子樹,若是它有奇數個結點,你再從裏面怎麼摳掉偶數結點的連通塊,它都不會變得合法。若是它原本就有偶數個結點,那麼你怎麼摳,都是合法的。blog
因此,咱們只須要切斷全部有偶數結點的子樹的父邊便可。string
而後再判一遍最後是否還是合法的。io
#include<cstdio> #include<cstring> using namespace std; int n; int e,first[100005],nex[200005],v[200005]; void AddEdge(int U,int V){ v[e]=V; nex[e]=first[U]; first[U]=e++; } bool vis[100005]; bool cut[200005]; int siz[100005]; int ans; void dfs(int U,int kara){ siz[U]=1; vis[U]=1; for(int i=first[U];i!=-1;i=nex[i]){ if(!vis[v[i]]){ dfs(v[i],i); siz[U]+=siz[v[i]]; } } if(kara!=-1 && siz[U]%2==0){ cut[kara]=cut[kara^1]=1; ++ans; } } int cnt; void df2(int U){ vis[U]=1; ++cnt; for(int i=first[U];i!=-1;i=nex[i]){ if(!vis[v[i]] && !cut[i]){ df2(v[i]); } } } int main(){ memset(first,-1,sizeof(first)); scanf("%d",&n); int x,y; for(int i=1;i<n;++i){ scanf("%d%d",&x,&y); AddEdge(x,y); AddEdge(y,x); } dfs(1,-1); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;++i){ if(!vis[i]){ cnt=0; df2(i); if(cnt%2==1){ puts("-1"); return 0; } } } printf("%d\n",ans); return 0; }