[ZROI138]赛尔号 欧拉回路

  • 欧拉回路中的点入度都等于出度,所以我们可以在图中构造一条欧拉回路
  • 考虑到图中度数为奇数的点有偶数个,所以我们把两两度数为奇数的点连一条边,这样所有点的度数都是偶数了
  • 答案就是度数为偶数的点的个数,跑一遍欧拉回路即可
  • 因为奇数点之间的连边不影响偶数点,而欧拉回路保证所有点入度等于出度,所以原图中的偶数点都符合条件
  • 注意图可能不连通

Code

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int N=2e5;
struct node{int y,n,id,pos;}e[N];
int lin[N],du[N],S[N],v[N],A[N],last=0,top=0,ans=0,len=1,n,m,x,y;
void read(int x,int y,int i){
	e[++len].y=y,e[len].n=lin[x],e[len].pos=i,e[len].id=0,lin[x]=len;
	e[++len].y=x,e[len].n=lin[y],e[len].pos=i,e[len].id=1,lin[y]=len;
}
void euler(int s){
	S[++top]=s;
	while(top){
		int x=S[top],i=lin[x];
		while(i&&v[i])i=e[i].n;
		if(i){
			S[++top]=e[i].y;
			v[i]=v[i^1]=1;
			A[e[i].pos]=e[i].id;
			lin[x]=e[i].n;
		}else top--;
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	rep(i,1,m){
		scanf("%d%d",&x,&y);
		du[x]++,du[y]++;
		read(x,y,i);
	}
	rep(i,1,n){
		if(du[i]&1){
			if(last)read(last,i,0),last=0;
			else last=i;
		}else ans++;
	}
	rep(i,1,n)euler(i);
	printf("%d\n",ans);
	rep(i,1,m)printf("%d",A[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/strangeDDDF/article/details/88225681
今日推荐