二分图判定方法:交叉染色
#include <bits/stdc++.h>
using namespace std;
int const N = 1e5 + 10;
int n,m;
vector<int>G[N];
int color[N];
bool dfs(int u,int c){
color[u] = c;
for(int i=0;i<G[u].size();i++){
int v = G[u][i];
if(color[v] == c) return false;
if(color[v] == 0 && !dfs(v,-c)) return false;
}
return true;
}
bool solve(){
for(int i=1;i<=n;i++){
if(!color[i])
if(!dfs(i,1)) return false;
}
return true;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
if(solve()) printf("Yes\n");
else printf("No\n");
return 0;
}
题解:
- 题目意思是单方面认识,团队里要相互认识。
- 把不认识的两个人用一条线相连。则相邻的两个人染色应该不一样。如果dfs过程中,有两个相邻的人染色相同,那么就矛盾。
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 100 + 10;
int n,color[N],tmp;
bool know[N][N],G[N][N];
bool dfs(int u,int c){
color[u] = c;
for(int i=1;i<=n;i++){
if(i != u && G[u][i]){
if(color[i] == c) return false;
if(color[i] == 0 && !dfs(i,-c)) return false;
}
}
return true;
}
bool solve(){
memset(color,0,sizeof(color));
for(int i=1;i<=n;i++)
if(!color[i]) //不同的连通分块
if(!dfs(i,1)) return false;
return true;
}
int main(){ //二分图判定,染色
while(~scanf("%d",&n)){
memset(know,false,sizeof(know));
memset(G,false,sizeof(G));
for(int i=1;i<=n;i++)
while(scanf("%d",&tmp) && tmp)
know[i][tmp] = true;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!know[i][j] || !know[j][i]) G[j][i] = G[i][j] = true; //只要有一方不认识,就不连
if(solve()) printf("YES\n");
else printf("NO\n");
}
return 0;
}
题解:
- 这一题和上一题本质是一样,问的不一样。此题要求分成两组,每一组内的人互相不认识,所以不用取补图了。认识的人连线即可。
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 200 + 10;
int n,m,s,t;
int mp[N][N],vis[N],linker[N],color[N];
bool dfs(int u,int c){
color[u] = c;
for(int i=1;i<=n;i++){
if(mp[u][i]){
if(color[i] == c) return false;
if(color[i] == 0 && !dfs(i,-c)) return false;
}
}
return true;
}
bool Judge(){
memset(color,0,sizeof(color));
for(int i=1;i<=n;i++){
if(!color[i])
if(!dfs(i,1)) return false;
}
return true;
}
bool dfs(int u){
for(int i=1;i<=n;i++){
if(vis[i] || !mp[u][i]) continue;
vis[i] = true;
if(linker[i] == -1 || dfs(linker[i])){
linker[i] = u;
return true;
}
}
return false;
}
int hunganry(){
int res = 0;
memset(linker,-1,sizeof(linker));
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(dfs(i)) res++;
}
return res;
}
int main(){
while(~scanf("%d%d",&n,&m)){
memset(mp,false,sizeof(mp));
for(int i=1;i<=m;i++){
scanf("%d%d",&s,&t);
mp[s][t] = mp[t][s] = true;
}
if(!Judge()) printf("No\n");
else{
printf("%d\n",hunganry()/2);
}
}
return 0;
}