【推导】Codeforces Round #484 (Div. 2) C. Cut 'em all!

题意:给你一棵树,让你切掉尽可能多的边,使得产生的所有连通块都有偶数个结点。

对于一棵子树,如果它有奇数个结点,你再从里面怎么抠掉偶数结点的连通块,它都不会变得合法。如果它本来就有偶数个结点,那么你怎么抠,都是合法的。

所以,我们只需要切断所有有偶数结点的子树的父边即可。

然后再判一遍最后是否仍是合法的。

#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;
}
posted @ 2018-05-18 11:45  AutSky_JadeK  阅读(216)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト