POJ 3207 【2-sat】.cpp

题意:

  panda和ikki.玩游戏..

  给出m个点对关系..这些点都在圆上..

  给点对连线..如果可以不交叉(可以在圆内或圆外连线)则panda赢..否则ikki.赢

  输入:

    给出n m 表示有n个点 m个点对

    接下来m行 有a b 表示点a 和 点b 之间有一条线

思路:

  2-sat..用来解决2个集合的冲突问题..

  这道题..冲突在于是在圆内和在圆外..

 

  把边看成点..

  然后看所有边连起来之后会不会出现冲突..即在圆外的边和在圆内的边同时出现在一个强连通分量里了..

  

  所以求出强连通分量..

  看交叉的两条边..用tarjan染色..

  如果冲突出现了(在圆内和在圆外出现在同一个分量里..则panda输了..)

  

Tips:

  nothing..?

 

Code:

  

View Code
  1 #include <stdio.h>

  2 #include <cstring>

  3 #include <algorithm>

  4 using namespace std;

  5 #define clr(x) memset(x, 0, sizeof(x))

  6 const int INF = 0x1f1f1f1f;

  7 const int MAXN = 510;

  8 

  9 struct Node

 10 {

 11     int x;

 12     int y;

 13 }node[MAXN];

 14 

 15 struct Edge

 16 {

 17     int to;

 18     int next;

 19 }edge[1000010];

 20 int head[MAXN];

 21 int tot;

 22 

 23 void add(int s, int u)

 24 {

 25     edge[tot].to = u;

 26     edge[tot].next = head[s];

 27     head[s] = tot++;

 28 

 29     edge[tot].to = s;

 30     edge[tot].next = head[u];

 31     head[u] = tot++;

 32 }

 33 

 34 int low[MAXN], dfn[MAXN];

 35 int sta[MAXN], ins[MAXN], col[MAXN];

 36 int ti, top, cnt;

 37 void tarjan(int u)

 38 {

 39     int i, j, k;

 40     dfn[u] = low[u] = ++ti;

 41     ins[u] = 1;

 42     sta[++top] = u;

 43     for(i = head[u]; i != -1; i = edge[i].next) {

 44         k = edge[i].to;

 45         if(!dfn[k]) {

 46             tarjan(k);

 47             low[u] = min(low[u], low[k]);

 48         } else if(ins[k]) {

 49             low[u] = min(low[u], dfn[k]);

 50         }

 51     }

 52     if(low[u] == dfn[u]) {

 53         cnt++;

 54         do

 55         {

 56             k = sta[top--];

 57             col[k] = cnt;

 58             ins[k] = 0;

 59         }while(u != k);

 60     }

 61 }

 62 

 63 

 64 int n, m;

 65 

 66 void solve_ta()

 67 {

 68     int i, j, k;

 69     clr(dfn);

 70     ti = top = cnt = 0;

 71     for(i = 1; i <= m; ++i)

 72     if(!dfn[i])

 73         tarjan(i);

 74 }

 75 

 76 bool solve()

 77 {

 78     int i, j, k;

 79     solve_ta();

 80     for(i = 1; i <= m; ++i)

 81         if(col[i] == col[i+m]) return false;

 82     return true;

 83 }

 84 

 85 int main()

 86 {

 87     int i, j, k;

 88     int a, b;

 89     while(scanf("%d %d", &n, &m) != EOF)

 90     {

 91         tot = 0;

 92         memset(head, 0xff, sizeof(head));

 93 

 94         for(i = 1; i <= m; ++i) {

 95             scanf("%d %d", &a, &b);

 96             if(a > b)

 97                 swap(a, b);

 98             node[i].x = a, node[i].y = b;

 99         }

100 

101         for(i = 1; i <= m; ++i)

102         for(j = i+1; j <= m; ++j)

103         if((node[i].x > node[j].x && node[i].x < node[j].y && node[i].y > node[j].y)

104          ||(node[j].x > node[i].x && node[j].x < node[i].y && node[j].y > node[j].y)){

105             add(i, j+m);

106             add(j, i+m);

107         }

108 

109         bool flag = solve();

110         if(flag) puts("panda is telling the truth...");

111         else puts("the evil panda is lying again");

112     }

113     return 0;

114 }

 

 

题目链接:http://poj.org/problem?id=3207

你可能感兴趣的:(poj)