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这些关系如何建图拉
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//看看会不会爆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 ") const int maxn = 10000 + 5; struct Tarjan{ int n; int pre[maxn*2], low[maxn*2], sccno[maxn*2], dfstime, scc_cnt; stack<int> s; vector<int> G[maxn*2]; void init(int n){ this->n = n; for (int i = 0; i <= n * 2; 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 = 0; i < len; i++){ int v = G[u][i]; if (pre[v] == -1){ 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, -1, sizeof(pre)); memset(low, 0, sizeof(low)); memset(sccno, 0, sizeof(sccno)); dfstime = scc_cnt = 0; for (int i = 0; i < 2 * n; i++){ if (pre[i] == -1) dfs(i); } for (int i = 0; i < 2 * n; i += 2){///如果两个点在同一个环里面,那么就返回false if (sccno[i] == sccno[i + 1]) return false; } return true; } }; Tarjan tar; int n, m; int main(){ while (scanf("%d%d", &n, &m) != EOF){ char ch[5]; tar.init(n); for (int i = 0; i < m; i++){ int a, b, c; scanf("%d%d%d%s", &a, &b, &c, ch); a = a * 2, b = b * 2;///刚开始都是0 if (ch[0] == 'A'){ if (c == 1){///a tar.add_edge(a ^ 1, a); tar.add_edge(b ^ 1, b); } else { tar.add_edge(a, b ^ 1); tar.add_edge(b, a ^ 1); } } else if (ch[0] == 'O'){ if (c == 1){ tar.add_edge(a ^ 1, b); tar.add_edge(b ^ 1, a); } else { tar.add_edge(a, a ^ 1); tar.add_edge(b, b ^ 1); } } else if (ch[0] == 'X'){ if (c == 1){ tar.add_edge(a, b ^ 1); tar.add_edge(b ^ 1, a); tar.add_edge(a ^ 1, b); tar.add_edge(b, a ^ 1); } else { tar.add_edge(a, b); tar.add_edge(b, a); tar.add_edge(a ^ 1, b ^ 1); tar.add_edge(b ^ 1, a ^ 1); } } } if (tar.solve()) puts("YES"); else puts("NO"); } return 0; }
具体可以看这个博客:http://www.hankcs.com/program/algorithm/poj-3678-katu-puzzle.html