题意:
m个查询,每个查询输入a b,表示 顶点a b之间涂色。 规定只能涂颜色0 或者颜色 1,一个节点相连的边 必须涂成相同的颜色。 问 ,输入m组 a b之后,会不会犯规。
思路:
判断 a b 所在的环 边的数量 是奇还是偶。 奇数就不能,偶数就能。
用并查集: 找到他们公共的祖先,判断(a到祖先的距离 + b到祖先的距离 +1 )的奇偶(最近的公共祖先 还是最远的公共祖先 都没关系,不影响奇偶) 。 如果a b没有公共祖先,就 f [fa] = fb合并起来就行
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=2e5+5; int f[N]; int getf(int x,int &s) { if(x!=f[x]) { s++; f[x]=getf( f[x],s); //画图,压缩路径,加起来 } return f[x]; } int main() { int n,k, a,b,v,fa,fb,q; int ans=0; while(cin>>n && n) { for(int i=0;i<=n;i++) f[i]=i; int flag=0; cin>>k; while(k--) { scanf("%d%d",&a,&b); if(flag==1) continue; int sa=0,sb=0; fa=getf(a,sa); fb=getf(b,sb); if(fa==fb){ if( (sa+sb+1)%2==1) //奇数环 { flag=1; continue; } } else { f[fa]=fb; } } if(flag) cout<<"NOT BICOLORABLE."<<endl; else cout<<"BICOLORABLE."<<endl; } }