Poj--3207(2-SAT)

2014-10-18 17:29:09

思路:这题就是需要正确建图,其他的就是模板了。输入的时候处理下使得输入的两个点前小后大,输入完后对所有的一对边扫一遍,找出矛盾边对,建图即可。

  (写这题前还是不懂tarjan为什么能够解决2-SAT问题,后来想的比较通了:比如 Si,Si’ 是拆成的一组点,显然要选其中一个,(设Si 所在的scc为 s1,Si’ 所在的scc为s2)如果选了Si 那么 s1内所有点都要选,所以如果Si、Si’在一个scc内的话就矛盾了。)

  1 /*************************************************************************i
  2     > File Name: 3207.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Sat 18 Oct 2014 03:00:35 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <stack>
 16 #include <queue>
 17 #include <iostream>
 18 #include <algorithm>
 19 using namespace std;
 20 #define lp (p << 1)
 21 #define rp (p << 1|1)
 22 #define getmid(l,r) (l + (r - l) / 2)
 23 #define MP(a,b) make_pair(a,b)
 24 typedef long long ll;
 25 const int INF = 1 << 30;
 26 const int maxn = 2010;
 27 
 28 int n,m;
 29 int first[maxn],next[maxn * maxn],ver[maxn * maxn],ecnt;
 30 int a[maxn],b[maxn];
 31 int low[maxn],dfn[maxn],sc[maxn],scnt,tot;
 32 stack<int> S;
 33 
 34 void Add_edge(int u,int v){
 35     next[++ecnt] = first[u];
 36     ver[ecnt] = v;
 37     first[u] = ecnt;
 38 }
 39 
 40 void Dfs(int p){
 41     dfn[p] = low[p] = ++tot;
 42     S.push(p);
 43     for(int i = first[p]; i != -1; i = next[i]){
 44         int v = ver[i];
 45         if(!dfn[v]){
 46             Dfs(v);
 47             low[p] = min(low[p],low[v]);
 48         }
 49         else if(!sc[v]){
 50             low[p] = min(low[p],dfn[v]);
 51         }
 52     }
 53     if(low[p] == dfn[p]){
 54         ++scnt;
 55         while(1){
 56             int x = S.top();
 57             S.pop();
 58             sc[x] = scnt;
 59             if(x == p) break;
 60         }
 61     }
 62 }
 63 
 64 bool Tarjan(){
 65     memset(low,0,sizeof(low));
 66     memset(dfn,0,sizeof(dfn));
 67     memset(sc,0,sizeof(sc));
 68     while(!S.empty()) S.pop();
 69     scnt = tot = 0;
 70     int top = 2 * m;
 71     for(int i = 0; i < top; ++i)
 72         if(!dfn[i]) Dfs(i);
 73     for(int i = 0; i < top; i += 2){
 74         if(sc[i] == sc[i + 1])
 75             return false;
 76     }
 77     return true;
 78 }
 79 
 80 void Init(){
 81     memset(first,-1,sizeof(first));
 82     ecnt = 0;
 83 }
 84 
 85 int main(){
 86     int x,y;
 87     Init();
 88     scanf("%d%d",&n,&m);
 89     for(int i = 0; i < m; ++i){
 90         scanf("%d%d",&x,&y);
 91         if(x > y) swap(x,y);
 92         a[i] = x;
 93         b[i] = y;
 94     }
 95     for(int i = 0; i < m; ++i){
 96         for(int j = i + 1; j < m; ++j){
 97             if(a[i] < a[j] && a[j] < b[i] && b[i] < b[j]){
 98                 Add_edge(i * 2,j * 2 + 1);
 99                 Add_edge(j * 2 + 1,i * 2);
100                 Add_edge(i * 2 + 1,j * 2);
101                 Add_edge(j * 2,i * 2 + 1);
102             }
103         }
104     }
105     if(Tarjan()) printf("panda is telling the truth...\n");
106     else printf("the evil panda is lying again\n");
107     return 0;
108 }

 

posted @ 2014-10-18 17:33  Naturain  阅读(128)  评论(0)    收藏  举报