首页 > 代码库 > poj2723-Get Luffy Out

poj2723-Get Luffy Out

一道2-SAT问题,每对钥匙需要加一条边,每扇门上的对应的要用的钥匙加一条边。

其实求解2-SAT问题,关键在于找到不能同时成立的条件,例如在本题中,每对钥匙不能同时使用,每扇门上的钥匙不能同时不使用。

 

 

  1 #include<cstdio>  2 #include<vector>  3 #include<cstring>  4 using namespace std;  5   6 const int maxn = 1<<12;  7   8 struct TwoSAT  9 { 10     int n; 11     vector<int> G[maxn*2]; 12     bool mark[maxn*2]; 13     int S[maxn*2], c; 14  15     bool dfs(int x) 16     { 17         if (mark[x^1]) return false; 18         if (mark[x]) return true; 19         mark[x] = true; 20         S[c++] = x; 21         for (int i = 0; i < G[x].size(); i++) 22             if (!dfs(G[x][i])) return false; 23         return true; 24     } 25  26     void init(int n) 27     { 28         this->n = n; 29         for (int i = 0; i < n*2; i++) G[i].clear(); 30         memset(mark, 0, sizeof(mark)); 31     } 32  33     // x = xval or y = yval 34     void add_clause(int x, int xval, int y, int yval) 35     { 36         x = x * 2 + xval; 37         y = y * 2 + yval; 38         G[x^1].push_back(y); 39         G[y^1].push_back(x); 40     } 41  42     bool solve() 43     { 44         for(int i = 0; i < n*2; i += 2) 45             if(!mark[i] && !mark[i+1]) 46             { 47                 c = 0; 48                 if(!dfs(i)) 49                 { 50                     while(c > 0) mark[S[--c]] = false; 51                     if(!dfs(i+1)) return false; 52                 } 53             } 54         return true; 55     } 56 }; 57  58  59 /////////////////////////////////////////////////////////////// 60 #include <iostream> 61 TwoSAT solver; 62 typedef pair<int ,int > CPair; 63 #define K1 first 64 #define K2 second 65 CPair doors[1<<12]; 66 CPair keys[1<<12]; 67 int n; 68  69  70 bool test(int nd) 71 { 72     solver.init(2*n); 73     // 重新构图 74     // 加入钥匙 75     for(int i=0;i<n;i++) 76     { 77         solver.add_clause(keys[i].K1,1,keys[i].K2,1); // 1表示使用key,0表示不使用 78     } 79     // 加入门 80     for(int i=0;i<=nd;i++) 81     { 82         solver.add_clause(doors[i].K1,0,doors[i].K2,0); // 1表示使用key,0表示不使用 83     } 84     return solver.solve(); 85 } 86  87 int main() 88 { 89     #ifndef ONLINE_JUDGE 90     freopen("in.txt","r",stdin); 91     #endif 92  93     int nDoor; 94     while(scanf("%d %d",&n,&nDoor),n+nDoor) 95     { 96         // 添加一对钥匙 97         for(int i=0;i<n;i++) 98         { 99             scanf("%d %d",&keys[i].K1,&keys[i].K2);100         }101 102         //103         for(int i=0;i<nDoor;i++)104         {105             scanf("%d %d",&doors[i].K1,&doors[i].K2);106         }107 108         int L=0,R=nDoor-1;109         while(L < R)110         {111             int M = L + (R-L+1)/2;112             if(test(M)) L = M;113             else R = M-1;114         }115         printf("%d\n",L+1);116     }117 118     return 0;119 }

 

poj2723-Get Luffy Out