Bicoloring (并查集/二分图)
题意:
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; } }
#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 n,m; int e[205][205] ; int book[N]; //用来标记每个顶点的颜色,即如果a b相连,顶点a 颜色为-1, //那么b的颜色 一定要为1 (只有1,-1这两种颜色 ),否则就不满足 int bfs() { queue<int>q; q.push(0); //应该题目 输入的全部数据一定有0顶点。 book[0]=-1; while(!q.empty()) { int t=q.front(); q.pop(); for(int i=0;i<=n;i++) { if(e[t][i]) //顶点t到顶点i有边 { if(book[i]) //i已经被遍历过 { if(book[t]==book[i]) return 1; } else { book[i]= -book[t]; q.push(i); } } } } return 0; } int main() { while(cin>>n && n) { mem(e,0); mem(book,0); cin>>m; for(int i=1;i<=m;i++) { int xx, yy; scanf("%d%d",&xx,&yy); e[xx][yy]=e[yy][xx]=1 ; } if(bfs()) cout<<"NOT BICOLORABLE."<<endl; else cout<<"BICOLORABLE."<<endl; } }