拖了一年才开始写这个题。。。
实际上是2-SAT模型问题,当初的想法整个就错了,我原先是遍历,如果A认识B,就将B放到A的那个集合中,实际上,如果B和另一组的C也认识,B也可以放在C的那一组(取决于B和两组中其他成员的认识程度)。
所以这个问题要从反面入手,要看不认识的人能不能分在两个组中。
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include <ctype.h>
using namespace std;
//hdu 4751
const int maxn=110;
int mp[maxn][maxn];
int g[maxn][maxn];//interference graph
int n;
int color[maxn];
bool dfs(int u,int pre,int state)//different state means different groups
{
color[u]=state;
for(int i=1;i<=n;i++)
{
if(g[u][i])
{
int v=i;
// if(v==pre) continue;//防止重复染色,比如pre将u染成1,u再将pre染成2就回到原先的状态,重复了,但是没有这一句也可以AC。。
// cout<<u<<" "<<v<<" "<<color[u]<<" "<<color[v]<<endl;
if(color[v]&&color[u]==color[v])
{
return false;
}
else
{
if(color[v]==0&&dfs(v,u,3-state)==false)
return false;
}
}
}
return true;
}
int main()
{
freopen("input.txt","r",stdin);
// freopen("data.txt","r",stdin);
// freopen("out1.txt","w",stdout);
while(scanf("%d",&n)!=EOF)
{
memset(mp,0,sizeof(mp));
memset(g,0,sizeof(g));
memset(color,0,sizeof(color));
for(int i=1;i<=n;i++)
{
while(true)
{
int c;
scanf("%d",&c);
if(c==0) break;
else
{
mp[i][c]=1;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(mp[i][j]==1&&mp[j][i]==1) continue;
g[i][j]=g[j][i]=1;//两个人不是相互认识,不可放在一组
}
}
int flg=0;
for(int i=1;i<=n;i++)
{
if(color[i]==0)
{
flg=dfs(i,i,1);//没有染过色,说明和之前的i认识,所以都染成1
// cout<<flg<<" "<<i<<endl;
if(flg==0)
{
printf("NO\n");
break;
}
}
}
if(flg)
{
printf("YES\n");
}
}
return 0;
}