您的位置:首页 > 其它

LightOJ 1251 - Forming the Council(2-SAT二分图)

2013-09-24 17:42 253 查看
/**
*  题目大意为有m人候选人,n个选举人,每个人有两个选择,
*  例如(+3, -1) +3表示选第3个人, -1表示不选第一个人,
* 要求最终选举出来的结果至少符合每个人的其中一种选择
* 很明显是二分图匹配,对于候选人来说,有两种情况,被选中和不被选中
*  举个例子,假设一个人选择的是(+3, +1),那么将可以将它分为两组(-1, +3) 和 (-3, +1);
*  当选3时-1也要选,当选1时,-3也要选,
* 假设又有一个人选了(+3, -2) 那么将会变成(-3, -2) ,(2, -3) 再和上面的集合融合
*  即为(-3, -2, 1) , (-1, +3) , (2, -3)有点不太好理解,还是看代码吧……
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

vector<int> f[16010], tmp;
bool flag[20010]; int m;

void add(int a, int b){
//这里a ^ 1 相当于是+ 和 - 的交换,比如3^1 == 2, 2 ^ 1 == 3
//2其实是-1, 3其实是1
f[a ^ 1].push_back(b);
f[b ^ 1].push_back(a);
}

bool dfs(int k){
if(flag[k]) return true;
if(flag[k ^ 1]) return false;
flag[k] = true;
tmp.push_back(k);
for(int i = 0; i < f[k].size(); ++i)
if( !dfs( f[k][i] ) ) return false;
return true;
}

bool two_SAT(){
for(int i = 1; i <= m; ++i){
if( !flag[2 * i] && !flag[2 * i + 1]){
tmp.clear();
if( !dfs(2 * i) ){
for(int j = 0; j < tmp.size(); ++j) flag[ tmp[j] ] = false;
if( !dfs(2 * i + 1) ) return false;
}
}
}
return true;
}

int main(){
int T, n, i, a, b;
scanf("%d", &T);
for(int cas = 1; cas <= T; ++cas){
printf("Case %d: ", cas);
scanf("%d%d", &n, &m);
for(i = 1; i <= m; ++i){
flag[2 * i] = flag[2 * i + 1] = false;
f[2 * i].clear(); f[2 * i + 1].clear();
}
for(i = 0; i < n; ++i){
scanf("%d%d", &a, &b);
//这里是把+,-融合到一块了,比如-1=>2, +1=>3, -2=>4, +2=>5依此类推
a = a > 0 ? 2 * a + 1: 2 * (-a);
b = b > 0 ? 2 * b + 1: 2 * (-b);
add(a, b);
}
if( two_SAT() ){
tmp.clear(); puts("Yes");
for(i = 1; i <= m; ++i)
if( flag[2 * i + 1] ) tmp.push_back(i);
if(tmp.size() == 0) puts("0");
else{
printf("%d ", tmp.size());
for(i = 0; i < tmp.size() - 1; ++i) printf("%d ", tmp[i]);
printf("%d\n", tmp[i]);
}
}
else puts("No");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: