题意:给定n个结点的图,问能否将它分成两个完全连通图。
思路分析:输入的图是有向图,我们先将它转化成无向图,因为如果1认识2, 2不认识1,那么1和2不相互认识。在明白一点,两个完全连通图的补图是二分图。然后我们只要判断补图是否为二分图就可以了。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<cstring>
#include<string>
#define N 105
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 10e-6
using namespace std;
int n,flag;
int G[N][N];
int color[N];
void dfs(int cur)
{
if(flag) return;
if(color[cur] == 0) color[cur] = 1;
int i;
for(i = 1; i <= n; i++)
{
if(G[cur][i] == 0)//原图的补图
if(color[i] == 0){
color[i] = 3 - color[cur];
dfs(i);
}
else if(color[i] == color[cur])
{
flag = 1;
return;
}
}
}
int main()
{
while(scanf("%d",&n) != EOF)
{
int i,j;
memset(G,0,sizeof(G));
for(i = 1; i <= n; i++)
{
int x;
while(scanf("%d",&x) && x)
G[i][x] = 1;
}
memset(color,0,sizeof(color));
for(i = 1; i <= n; i++)
for(j = 1; j <= i; j++)
{
if(i == j) {G[i][j] = 1;continue;}
if(G[i][j] == 0 || G[j][i] == 0)
G[i][j] = G[j][i] = 0;
}
flag = 0;
for(i = 1; i <= n; i++)
if(color[i] == 0)
dfs(i);
if(flag == 1) printf("NO\n");
else printf("YES\n");
}
return 0;
}