题意:中文题。
把每一队看成是一组,队长为 i << 2, 队员都为 i << 2 | 1, 这样就能转化为2 - SAT问题。
2-SAT问题最主要的就是一组里有对立的两个元素,通过他们的belong去判断是否yes。组间元素的关系去连边。
链接:hdu - 1824
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 2005;
const int maxm = 10005;
struct node {
int s, t;
int nxt;
} e[maxm];
int n, m;
int idx, ans, tp, cont;
int dfn[maxn], vis[maxn], low[maxn], head[maxn], st[maxn], belong[maxn];
void init() {
cont = 0;
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
memset(dfn, 0, sizeof(dfn));
memset(vis, 0, sizeof(vis));
idx = tp = ans = 0;
}
void add(int s, int t) {
e[cont].s = s;
e[cont].t = t;
e[cont].nxt = head[s];
head[s] = cont++;
}
void tarjan(int u) {
dfn[u] = low[u] = ++idx;
vis[u] = 1;
st[++tp] = u;
int v ;
for(int i = head[u]; i != -1; i = e[i].nxt) {
v = e[i].t ;
if(!dfn[v]) {
tarjan(v) ;
low[u] = min(low[u],low[v]);
}
else if(vis[v])
low[u] = min(low[u],dfn[v]);
}
if(dfn[u] == low[u]) {
ans++;
while(1) {
v = st[tp--];
vis[v] = 0;
belong[v] = ans;
if(v == u)
break;
}
}
}
bool _2sat() {
for(int i = 0; i < 2 * n; i++)
if(!dfn[i])
tarjan(i) ;
for(int i = 0; i < n; i++)
if(belong[i << 1] == belong[i << 1 | 1])//矛盾
return false;
return true;
}
int in[maxn];
int main()
{
while(~scanf("%d %d", &n, &m)) {
init();
for(int i = 0; i < n; i++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
in[a] = i << 1;
in[b] = in[c] = i << 1 | 1;
}
while(m--) {
int a, b;
scanf("%d %d", &a, &b);
add(in[a], in[b] ^ 1);
add(in[b], in[a] ^ 1);
}
if(_2sat())
printf("yes\n");
else
printf("no\n");
}
return 0 ;
}