设在第一个集合中是 0 0 0,在第二个集合中是 1 1 1
设 u 1 , u 2 . . . u x u_1,u_2...u_x u1,u2...ux和 u i u_i ui有边
那么和 u i u_i ui相等的节点是奇数个,其他节点都是 u i ⊕ 1 u_i\oplus 1 ui⊕1
那么显然需要分 u i u_i ui朋友的奇偶来分的。
设 u i u_i ui的朋友是奇数个
那么和 u i u_i ui相等的节点也是奇数个,所以这部分和 u i u_i ui异或是零
而且其他和 u i u_i ui不等的节点间是偶数个,所以异或值为零
所以有 u 1 ⊕ u 2 ⊕ . . . u x ⊕ u i = 0 u_1\oplus u_2\oplus ...u_x\oplus u_i=0 u1⊕u2⊕...ux⊕ui=0
设 u i u_i ui的朋友是偶数个
那么和 u i u_i ui相等的节点是奇数个,这部分和 u i u_i ui异或为零
其他和 u i u_i ui不等的节点也是奇数个,所以奇数个相同的数异或就是自己,也就是 u i ⊕ 1 u_i\oplus 1 ui⊕1
所以有 u 1 ⊕ u 2 ⊕ . . . ⊕ u i = u i ⊕ 1 u_1\oplus u_2\oplus...\oplus u_i=u_i\oplus 1 u1⊕u2⊕...⊕ui=ui⊕1
就是 u 1 ⊕ u 2 ⊕ . . . u x = 1 u_1\oplus u_2\oplus ...u_x=1 u1⊕u2⊕...ux=1
解这个异或方程组即可
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
%:pragma GCC optimize("-fgcse")
%:pragma GCC optimize("-fgcse-lm")
%:pragma GCC optimize("-fipa-sra")
%:pragma GCC optimize("-ftree-pre")
%:pragma GCC optimize("-ftree-vrp")
%:pragma GCC optimize("-fpeephole2")
%:pragma GCC optimize("-ffast-math")
%:pragma GCC optimize("-fsched-spec")
%:pragma GCC optimize("unroll-loops")
%:pragma GCC optimize("-falign-jumps")
%:pragma GCC optimize("-falign-loops")
%:pragma GCC optimize("-falign-labels")
%:pragma GCC optimize("-fdevirtualize")
%:pragma GCC optimize("-fcaller-saves")
%:pragma GCC optimize("-fcrossjumping")
%:pragma GCC optimize("-fthread-jumps")
%:pragma GCC optimize("-funroll-loops")
%:pragma GCC optimize("-fwhole-program")
%:pragma GCC optimize("-freorder-blocks")
%:pragma GCC optimize("-fschedule-insns")
%:pragma GCC optimize("inline-functions")
%:pragma GCC optimize("-ftree-tail-merge")
%:pragma GCC optimize("-fschedule-insns2")
%:pragma GCC optimize("-fstrict-aliasing")
%:pragma GCC optimize("-fstrict-overflow")
%:pragma GCC optimize("-falign-functions")
%:pragma GCC optimize("-fcse-skip-blocks")
%:pragma GCC optimize("-fcse-follow-jumps")
%:pragma GCC optimize("-fsched-interblock")
%:pragma GCC optimize("-fpartial-inlining")
%:pragma GCC optimize("no-stack-protector")
%:pragma GCC optimize("-freorder-functions")
%:pragma GCC optimize("-findirect-inlining")
%:pragma GCC optimize("-fhoist-adjacent-loads")
%:pragma GCC optimize("-frerun-cse-after-loop")
%:pragma GCC optimize("inline-small-functions")
%:pragma GCC optimize("-finline-small-functions")
%:pragma GCC optimize("-ftree-switch-conversion")
%:pragma GCC optimize("-foptimize-sibling-calls")
%:pragma GCC optimize("-fexpensive-optimizations")
%:pragma GCC optimize("-funsafe-loop-optimizations")
%:pragma GCC optimize("inline-functions-called-once")
%:pragma GCC optimize("-fdelete-null-pointer-checks")
const int maxn = 309;
int n,k,a[maxn][maxn],in[maxn],ans[maxn];
int freedom[maxn],num;//存储自由元的位置
int Gauss(int m,int n)
{//m为行数,n为列数(不含常数列)
int col=0,k=0;//col为列号,k为行号
for(;k<m&&col<n;k++,col++){
int r=k;
for(int i=k+1;i<m;i++){//找系数最大的列
if(abs(a[i][col])>a[r][col])r=i;
}
if(a[r][col]==0){//如果一列都为0就跳过
freedom[num++]=col;//存储自由元的列数
k--;continue;
}
if(r!=k)for(int i=col;i<=n;i++){//交换行
swap(a[k][i],a[r][i]);
}
for(int i=k+1;i<m;i++){//消元
if(abs(a[i][col])!=0){
for(int j=col;j<=n;j++){
a[i][j]^=a[k][j];
}
//a[i][j]=0;
}
}
}
for(int i=k;i<m;i++){
if(a[i][col]!=0)return -1;//无解标志
}
if(k<n)return n-k;//如果有自由元,返回自由元个数
for(int i=n-1;i>=0;i--){
ans[i]=a[i][n];
for(int j=i+1;j<n;j++){
ans[i]^=(a[i][j]&&ans[j]);
}
}
return 0;//有解标志
}
int main()
{
cin >> n >> k;
for(int i=1;i<=k;i++)
{
int l,r; cin >> l >> r;
l--,r--;
in[l]++,in[r]++; a[l][r]=1; a[r][l]=1;
}
for(int i=0;i<n;i++)
{
if( in[i]%2==0 ) a[i][n] = 1;
else a[i][i] = 1;
}
if( Gauss(n,n)!=-1 ) cout << "Y";
else cout << "N";
return 0;
}