您的位置:首页 > 其它

UVA 1391 2-SAT

2015-08-27 22:08 274 查看
UVA 1391

题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=38529
题意:

n个人,年龄在均值以下的去A或C,以上去B或C。

有m中仇恨方式,问一种合理的方案并输出。

思路:

2-SAT

我没有看题解哦

我没有看题解哦

我没有看题解哦

我没有看题解哦~

刚开始想怎么去处理三种状态,然后按照之前打版的方法打了一发连样例都没有过。

然后把加边的地方lin[u^1].push_back(v)改成lin[u].push_back(v^1)。居然过样例了。嗯WA了。

想了想是不是因为对于每个点属于A或者B的情况、即取他为TRUE的情况都没有点接在后面,每次dfs就直接赋值为TRUE。试着翻转了一下每个点为TRUE的状态,即设0为FALSE,1为TRUE。WA。

玩了两分钟手机,决定从原理上想一想。

2-SAT的原理是数理逻辑。假设A或B真,则A假时B一定真,B假时A一定真,然而A真B真的情况也是存在的。但本题存在A真B真都不合法的情况,就是A和B的年龄都在一个年龄段上时。

关键代码:

if(age[u/2] == age[v/2]){

lin[u].push_back(v^1);

lin[v].push_back(u^1);

}

然后就A了,WA了四发吧,可以去打省赛了。



源码:

#include <cstdio>

#include <cmath>

#include <cstdlib>

#include <cstring>

#include <algorithm>

#include <iostream>

#include <stack>

#include <queue>

#include <vector>

using namespace std;

const int MAXN = 100000 + 5;

vector<int>lin[MAXN * 2];

stack<int>sta;

int n, m;

int age[MAXN];

int valid[MAXN * 2];

double ave;

bool dfs(int u)

{

if(valid[u^1]) return false;

if(valid[u]) return true;

valid[u] = 1;

sta.push(u);

for(int i = 0 ; i < (int)lin[u].size() ; i++){

int v = lin[u][i];

if(!dfs(v)) return false;

}

return true;

}

bool solve()

{

while(!sta.empty()) sta.pop();

memset(valid, 0, sizeof(valid));

for(int i = 0 ; i < 2 * n ; i+=2){

if(!valid[i] && !valid[i^1]){

if(!dfs(i)){

while(!sta.empty()){

int org = sta.top(); sta.pop();

valid[org] = 0;

if(org == i) break;

}

if(!dfs(i^1)) return false;

}

}

}

return true;

}

int main()

{

while(scanf("%d%d", &n, &m) != EOF && n + m){

ave = 0;

for(int i = 0 ; i < n ; i++)

scanf("%d", &age[i]), ave += age[i];

for(int i = 0 ; i < 2 * n ; i++)

lin[i].clear();

ave /= (1.0 * n);

for(int i = 0 ; i < n ; i++){

if(age[i] >= ave) age[i] = 0;

else age[i] = 1;

}

int u, v;

for(int i = 1 ; i <= m ; i++){

scanf("%d%d", &u, &v);

u--, v--;

u *= 2, v *= 2;

lin[u^1].push_back(v);

lin[v^1].push_back(u);

if(age[u/2] == age[v/2]){

lin[u].push_back(v^1);

lin[v].push_back(u^1);

}

}

// for(int i = 0 ; i < 2 * n ; i++){

// printf("lin[%d] = ", i) ;

// for(int j = 0 ; j < (int)lin[i].size() ; j++)

// printf("%d ", lin[i][j]);

// printf("\n");

// }

if(solve()){

for(int i = 0 ; i < 2 * n ; i += 2){

if(valid[i]){

if(!age[i / 2]) printf("A\n");

else printf("B\n");

}

else printf("C\n");

}

}

else

printf("No solution\n");

}

return 0;

}

/*

16 20

21

22

23

24

25

26

27

28

101

102

103

104

105

106

107

108

1 2

3 4

5 6

7 8

9 10

11 12

13 14

15 16

1 10

2 9

3 12

4 11

5 14

6 13

7 16

8 15

1 12

1 13

3 16

6 15

0 0

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: