标签:
Description
Input
Output
Sample Input
input | output |
---|---|
3 4 1 2 2 3 1 4 |
Yes 2 3 4 |
6 4 1 2 1 3 1 4 2 3 2 4 3 4 |
No |
题意:给出n对点a,b 要求从没对点中选出一个,且最终选出的点n个数不能存在相同的。输入数据满足每种数最多出现3次,最少出现1次
思路:第i对点的编号2*i, 2*i+1, 因为每个数最多出现3次,那么完全可以枚举每个数,然后相同的数之间的编号连一条边,表示这两个编号不能同时选,这样跑完twosat就能得到一个满足情况的解或无解。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <cstdlib> #include <map> #include <set> #include <cmath> using namespace std; const int N = 2e6 + 100; struct Edge { int to, nex; }e[N]; int head[N], tot; void init() { tot = 0; memset(head, -1, sizeof head); } void add(int u, int v) { e[tot].to = v; e[tot].nex = head[u]; head[u] = tot++; } int Low[N], DFN[N], Stack[N], Belong[N]; int Index, top; int scc; bool Instack[N]; int num[N]; void Tarjan(int u) { int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Instack[u] = true; for(int i = head[u]; ~i; i = e[i].nex) { v = e[i].to; if(!DFN[v]) { Tarjan(v); if(Low[u] > Low[v]) Low[u] = Low[v]; }else if(Instack[v] && Low[u] > DFN[v]) Low[u] = DFN[v]; } if(Low[u] == DFN[u]) { scc++; do { v = Stack[--top]; Instack[v] = false; Belong[v] = scc; num[scc]++; }while(v != u); } } bool solvable(int n) { memset(DFN, 0, sizeof DFN); memset(Instack, false, sizeof Instack); memset(num, 0, sizeof num); Index = scc = top = 0; for(int i = 0; i < n; ++i) if(!DFN[i]) Tarjan(i); for(int i = 0; i < n; i += 2) { if(Belong[i] == Belong[i ^ 1]) return false; } return true; } queue<int> q1, q2; vector<vector<int> >dag; int vis[N]; int indeg[N]; int cf[N]; void solve(int n) { dag.assign(scc+1, vector<int>()); memset(indeg, 0, sizeof indeg); memset(vis, 0, sizeof vis); for(int u = 0; u < n; ++u) { for(int i = head[u]; ~i; i = e[i].nex) { int v = e[i].to; if(Belong[u] != Belong[v]) { dag[ Belong[v] ].push_back(Belong[u]); indeg[ Belong[u] ]++; } } } for(int i = 0; i < n; i += 2) { cf[ Belong[i] ] = Belong[i ^ 1]; cf[ Belong[i ^ 1] ] = Belong[i]; } while(!q1.empty()) q1.pop(); while(!q2.empty()) q2.pop(); for(int i = 1; i <= scc; ++i) if(indeg[i] == 0) q1.push(i); while(!q1.empty()) { int u = q1.front(); q1.pop(); if(vis[u] == 0) { vis[u] = 1; vis[ cf[u] ] = 0; } int sz = dag[u].size(); for(int i = 0; i < sz; ++i) { indeg[ dag[u][i] ]--; if(indeg[ dag[u][i] ] == 0) q1.push(dag[u][i]); } } } int r[N]; vector<int> g[N]; int main() { #ifdef LOCAL freopen("in", "r", stdin); #endif int n, m; while(~scanf("%d%d", &m, &n)) { init(); int tot = 0; int u, v; for(int i = 0; i < m; ++i) { scanf("%d%d", &u, &v); r[tot++] = u; r[tot++] = v; g[u].push_back(2 * i); g[v].push_back(2 * i + 1); } for(int i = 1; i <= n; ++i) { int sx = g[i].size(); for(int j1 = 0; j1 < sx; ++j1) { for(int j2 = j1 + 1; j2 < sx; ++j2) { int v1 = g[i][j1]; int v2 = g[i][j2]; add(v1, v2 ^ 1); add(v2, v1 ^ 1); } } } if(solvable(2 * m)) { solve(2 * m); puts("Yes"); for(int i = 0; i < m; ++i) { if(vis[ Belong[2 * i] ]) printf("%d\n", r[2 * i + 1]); else printf("%d\n", r[2 * i]); } }else puts("No"); } return 0; }
URAL 2089 Experienced coach Twosat
标签:
原文地址:http://www.cnblogs.com/orchidzjl/p/5814116.html