题意:给你i认识j但是不具有对称性,也就是j不认识i;然后问是否能分为两组,两组中都是认识的人;
我头一次写二分图,最原始的二分图是是否相邻的能被两种不同的颜色染色;然后这道题可以这样抽象:
把不同的人当做顶点,如果两个人不认识就加边:
比如1不认识2,2不认识3,那么:
很明显这个图是二分图;因为1号顶点可被染成1的颜色,2号顶点可以被染成-1的颜色,3号顶点可以被染成1颜色;所以这道题就是去找不认识的人然后用邻接表建立一个无向图;之后dfs遍历所有连通块,因为如果1,2,3都互相认识那么建立的图就应该是:
这样就可以随便染色了;所以需要用一个for+dfs遍历所有连通块:
AC代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=200;
int color[maxn];
int R[200][200];
vector<int> edge[maxn];
bool dfs(int v,int c){
color[v]=c;
for(int i=0;i<edge[v].size();i++){//遍历v点所能到达的点
if(color[edge[v][i]]==c)return false;//如果被染为一样的就false
if(color[edge[v][i]]==0&&!dfs(edge[v][i],-c))return false;//如果没有颜色,那么看一下一点是否满足条件
}
return true;//如果都OK,就返回true
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
memset(color,0,sizeof(color));//注意每次更新
memset(R,0,sizeof(R));
for(int i=0;i<maxn;i++)edge[i].clear();
int a;
for(int i=1;i<=n;i++){
while(scanf("%d",&a)&&a){
R[i][a]=1;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
if(R[i][j]==0){//建立无向图,因为i不认识j所以根据图应该是建立双向的
edge[i].push_back(j);
edge[j].push_back(i);
}
}
}
int f=0;
for(int i=1;i<=n;i++){//遍历所有连通块
if(color[i]==0){
if(!dfs(i,1)){
puts("NO");f=1;break;
}
}
}
if(!f)puts("YES");
}
return 0;
}