有一群人,有的人认识某些人(认识的关系是单向的)。
现在需要将这些人分成两个部分,每一个部分中所有的人都是两两认识的。
2SAT,每个人要么属于第一个集合,要么属于第二个集合。
补图+二分图判定。
#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 102;
int g[maxn][maxn];
int col[maxn];
int n;
bool is_bi(int u){
for (int i=1; i<=n; i++){
if (g[u][i] && u!=i){
if (col[i] == col[u])
return false;
if (!col[i]){
col[i] = 3 - col[u];
if (!is_bi(i))
return false;
}
}
}
return true;
}
int main(){
int p;
int i, j, k;
while (scanf("%d",&n)!=EOF){
memset(g, 0, sizeof(g));
memset(col, 0, sizeof(col));
for (i=1; i<=n; i++){
while (scanf("%d",&p),p){
g[i][p] = 1;
}
}
for (i=1; i<=n; i++){
for (j=i+1; j<=n; j++){
if (g[i][j] && g[j][i]){
g[i][j] = g[j][i] = 0;
}
else g[i][j] = g[j][i] = 1;
}
}
int flag = 0;
for (i=1; i<=n; i++){
if (!col[i]){
col[i] = 1;
if (!is_bi(i)){
flag = 1;
break;
}
}
}
if (flag)printf("NO\n");
else printf("YES\n");
}
return 0;
}
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define clr(x)memset(x,0,sizeof(x))
int abs(int x){if(x>0)return x;return -x;}
const int maxn=10010;
struct node{
int to;
int next;
}q[10010];
int head[maxn];
int tot;
void add(int s,int u){
q[tot].to=u;
q[tot].next=head[s];
head[s]=tot++;
}
bool ins[maxn];
int color[maxn];
int dfn[maxn],low[maxn],stack[maxn];
int ti,sn,top;
void tarjan(int u){
dfn[u]=low[u]=++ti;
stack[++top]=u;
ins[u]=true;
int i,k;
for(i=head[u];i;i=q[i].next){
k=q[i].to;
if(dfn[k]==0){
tarjan(k);
if(low[k]<low[u])low[u]=low[k];
}
else if(ins[k]&&dfn[k]<low[u])
low[u]=dfn[k];
}
if(dfn[u]==low[u]){
sn++;
do{
k=stack[top--];
ins[k]=false;
color[k]=sn;
}while(k!=u);
}
}
void init(){
clr(low);
clr(dfn);
clr(ins);
clr(head);
tot=1;
top=-1;
sn=ti=0;
}
int g[300][300];
int main(){
int i,j,n,p;
while(scanf("%d",&n)!=EOF){
init();
clr(g);
for (i=0;i<n;i++){
while(scanf("%d",&p),p){
p--;
g[i][p] = 1;
}
}
for(i=0;i<n;i++){
for (j=i+1;j<n;j++){
if (g[i][j]&&g[j][i]){
g[i][j]=g[j][i]=0;
}
else {g[i][j]=g[j][i]=1;add(i,j+n);add(j,i+n);add(i+n,j);add(j+n,i);}
}
}
for(i=0;i<2*n;i++)
if(dfn[i]==0)tarjan(i);
int flag=0;
for(i=0;i<n;i++)
if(color[i]==color[i+n])flag=1;
if(flag)printf("NO\n");
else printf("YES\n");
}
return 0;
}