您的位置:首页 > 理论基础 > 计算机网络

HDUOJ 4751 Divide Groups 2013南京网络赛1004

2013-09-21 20:25 447 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4751

不得不吐槽一下坑爹的出题人,题目不知道改了多少个。。。不过也就早过一题,晚过一题的问题(因为只A了一题),弱到不能再弱。吃翔去。。。

题目意思就是把一幅有向图的点分成两个集合,使得每个集合内的点构成完全图。

可以转化成二分图,然后染色解决。我们用邻接矩阵保存边,(有正反),然后重新定义连通的关系:如果两个点之间原来有正反两边,那么新的图这两点不相邻,否则相邻,于是得到新图,我们将会得到一些(可能一个)连通片,对于一个连通片相邻的节点必须属于不同集合(原来并不是双向连通),所以可以DFS, 对相邻的点而二染色,当发现将要访问的点已经被染色,则判断他是否是你希望的颜色,不是就矛盾了,否则对于这个连通片,可以二分,而对于不同连通片,完全是独立的,因为没边,说明原来有双向边,可以在同一个集合里。

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<cstring>
#include<cmath>
using namespace std;
#define N 105
#define sl(s) strlen(s)
#define mem(a) memset(a, 0, sizeof(a))
#define dou double

int s[105][105], vis[105], x[105][105], fl, c[105];

void dfs(int x, int d){
int i, j, k;
vis[x] = 1;
c[x] = d & 1;
if (!fl) return ;
for (i = 1; i <= n; ++i){
if (x[x][i]){
if (vis[i]){
if (c[i] + c[x] != 1) fl = 0;
}
else{
dfs(i, d + 1);
}
}
}
}

int main(){
int n, i, j, k;
while (cin >> n){
mem(s), mem(vis), mem(c), mem(x)
for (i = 1; i <= n; ++i)
while (cin >> tem, tem) s[i][tem] = 1;
for (i = 1; i <= n; ++i)
for (j = i + 1; j <= n; ++j)
if (s[i][j] + s[j][i] == 1){
x[i][j] = x[j][i] = 1;
}
fl = 1;
for (i = 1; i < n; ++i){
if (vis[i]) dfs(i, 0);
}
if (fl) printf("YES\n");
else printf("NO\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息