http://poj.org/problem?id=3678
题目大意:就是给你n个点,m条边,每个点都可以取值为0或者1,边上都会有一个符号op(op=xor or and三种)和一个权值c。然后问你如何选择每个点的值,才能让所有点都满足x[i] op x[j] = c
思路:
这题学会了好多东西哇,至少我明白了xor,or,and这些关系如何建图拉
//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
#include<iostream>
#include<utility>
#include<stack>
#include<stdlib.h>
#include<time.h>
#include<cmath>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = + ;
struct Tarjan{
int n;
int pre[maxn*], low[maxn*], sccno[maxn*], dfstime, scc_cnt;
stack<int> s;
vector<int> G[maxn*];
void init(int n){
this->n = n;
for (int i = ; i <= n * ; i++) G[i].clear();
while (!s.empty()) s.pop();
}
void add_edge(int x, int y){
G[x].push_back(y);
}
void dfs(int u){
pre[u] = low[u] = ++dfstime;
int len = G[u].size();
s.push(u);
for (int i = ; i < len; i++){
int v = G[u][i];
if (pre[v] == -){
dfs(v);
low[u] = min(low[u], low[v]);
}
else if (!sccno[v]){///下面为什么是pre[v]而不是low[v](两者都可以)
low[u] = min(low[u], pre[v]);///因为环装最后总会变回来,一样的
}
}
if (low[u] == pre[u]){
scc_cnt++;
while (true){
int x = s.top(); s.pop();
sccno[x] = scc_cnt;
if (x == u) break;
}
}
return ;
} bool solve(){///看情况修改solve
memset(pre, -, sizeof(pre));
memset(low, , sizeof(low));
memset(sccno, , sizeof(sccno));
dfstime = scc_cnt = ;
for (int i = ; i < * n; i++){
if (pre[i] == -) dfs(i);
}
for (int i = ; i < * n; i += ){///如果两个点在同一个环里面,那么就返回false
if (sccno[i] == sccno[i + ]) return false;
}
return true;
}
};
Tarjan tar;
int n, m; int main(){
while (scanf("%d%d", &n, &m) != EOF){
char ch[];
tar.init(n);
for (int i = ; i < m; i++){
int a, b, c; scanf("%d%d%d%s", &a, &b, &c, ch);
a = a * , b = b * ;///刚开始都是0
if (ch[] == 'A'){
if (c == ){///a
tar.add_edge(a ^ , a);
tar.add_edge(b ^ , b);
}
else {
tar.add_edge(a, b ^ );
tar.add_edge(b, a ^ );
}
}
else if (ch[] == 'O'){
if (c == ){
tar.add_edge(a ^ , b);
tar.add_edge(b ^ , a);
}
else {
tar.add_edge(a, a ^ );
tar.add_edge(b, b ^ );
}
}
else if (ch[] == 'X'){
if (c == ){
tar.add_edge(a, b ^ );
tar.add_edge(b ^ , a);
tar.add_edge(a ^ , b);
tar.add_edge(b, a ^ );
}
else {
tar.add_edge(a, b);
tar.add_edge(b, a);
tar.add_edge(a ^ , b ^ );
tar.add_edge(b ^ , a ^ );
}
}
}
if (tar.solve()) puts("YES");
else puts("NO");
}
return ;
}
具体可以看这个博客:http://www.hankcs.com/program/algorithm/poj-3678-katu-puzzle.html