标签:hat sample friend mes input start record 连通 ack
Description
Input
Output
Sample Input
3 6 0 3 1 2 4 5 0 1 0 2 4 1 4 2 3 5 2 2 0 0
Sample Output
4
今天学习了 2-sat问题 这是一个现实中经常遇到的问题可以转化为图论去解决
有m扇门,每扇门都有两把锁,只要打开其中一把就可以打开这扇门,
打开了第i扇门才能继续开第i+1扇门。
现在有2n个钥匙,每两个绑在一起,使用了一个就不能使用另一个。
问最多能开几扇门。
这个就是 2-sat问题的模板题
以下是这类问题的基本的解题思路
a->b+2*n 表示 选a不选b
门的建边就要 a+2*n->b
然后判断 a和a+2*n 在不在同一个强连通分量内
回到题目来 这题的话网上普遍二分解决 因为这样快啊
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <string> 6 #include <algorithm> 7 #include <queue> 8 #include <stack> 9 10 using namespace std; 11 const int maxn = 1e5 + 10; 12 const int mod = 1e9 + 7 ; 13 const int INF = 0x7ffffff; 14 struct node { 15 int v, next; 16 } edge[maxn]; 17 int head[maxn], dfn[maxn], low[maxn]; 18 int s[maxn], belong[maxn], instack[maxn]; 19 int tot, cnt, top, flag, n, m; 20 void init() { 21 tot = cnt = top = flag = 0; 22 memset(s, 0, sizeof(s)); 23 memset(head, -1, sizeof(head)); 24 memset(dfn, 0, sizeof(dfn)); 25 memset(instack, 0, sizeof(instack)); 26 } 27 void add(int u, int v ) { 28 edge[tot].v = v; 29 edge[tot].next = head[u]; 30 head[u] = tot++; 31 } 32 void tarjin(int v) { 33 dfn[v] = low[v] = ++flag; 34 instack[v] = 1; 35 s[top++] = v; 36 for (int i = head[v] ; ~i ; i = edge[i].next ) { 37 int j = edge[i].v; 38 if (!dfn[j]) { 39 tarjin(j); 40 low[v] = min(low[v], low[j]); 41 } else if (instack[j]) low[v] = min(low[v], dfn[j]); 42 } 43 if (dfn[v] == low[v]) { 44 cnt++; 45 int t; 46 do { 47 t = s[--top]; 48 instack[t] = 0; 49 belong[t] = cnt; 50 } while(t != v) ; 51 } 52 } 53 struct p { 54 int u, v; 55 } qu[maxn]; 56 int check(int mid) { 57 init(); 58 for (int i = 0 ; i < n ; i++) { 59 add(qu[i].v, qu[i].u + 2 * n); 60 add(qu[i].u, qu[i].v + 2 * n); 61 } 62 for (int i = 0 ; i < mid ; i++ ) { 63 add(qu[i + n].u + 2 * n, qu[i+n].v); 64 add(qu[i + n].v + 2 * n, qu[i+n].u); 65 } 66 for (int i = 0 ; i < 4 * n ; i++) 67 if (!dfn[i]) tarjin(i); 68 for (int i = 0 ; i < 2 * n ; i++) 69 if (belong[i] == belong[i + 2 * n]) return 0; 70 return 1; 71 } 72 int main() { 73 while(scanf("%d%d", &n, &m) != EOF) { 74 if (n == 0 && m == 0 ) break; 75 for (int i = 0 ; i < n ; i++) 76 scanf("%d%d", &qu[i].u, &qu[i].v); 77 for (int i = 0 ; i < m ; i++) 78 scanf("%d%d", &qu[i + n].u, &qu[i + n].v); 79 int low = 0, high = m, mid; 80 while(low <= high) { 81 mid = (low + high) / 2; 82 if (check(mid)) low = mid + 1; 83 else high = mid - 1; 84 } 85 printf("%d\n", high); 86 } 87 return 0; 88 }
poj 2723 Get Luffy Out-2-sat问题
标签:hat sample friend mes input start record 连通 ack
原文地址:https://www.cnblogs.com/qldabiaoge/p/9092918.html