POJ3207(2-SAT+模型3)

题目链接:https://vjudge.net/problem/POJ-3207

题目意思:有一个圆,给出一些边连接着两个点,边可以从圆里连,也可以从圆外连,问是否可以不相交

对于边i,ji,j限制条件为不相交,即不在同一个集合中

因此我们将这个问题转化为了2-SAT问题

ii表示边ii在圆内,ii′表示ii在圆外

(i,j)(i,j)在圆内相交,那么它们在圆外也一定相交

如果边i,ji,j在圆内相交

那么就从ii连向jj′(i内j外),从jj′连向ii(i内j外),从jj连向ii′(j内i外),从ii′连向jj(j内i外)

然后来一遍tarjan就好了

 

 1 #include<cstdio>
 2 #include<string.h>
 3 #include<vector>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N = 1000005;
 7 int n,m,cnt,tot,top,scc,dfn[N],low[N],vis[N],sta[N],S[N],T[N],belong[N];
 8 vector<int> G[2*N];
 9 void init()
10 {
11     memset(dfn,0,sizeof(dfn));
12     memset(low,0,sizeof(low));
13     memset(vis,0,sizeof(vis));
14     memset(sta,0,sizeof(sta));
15     memset(belong,0,sizeof(belong));
16     cnt = tot = top = scc = 0;
17 }
18 void add(int u,int v)
19 {
20     G[u].push_back(v);
21 }
22 void tarjan(int u)
23 {
24     dfn[u]  = low[u] = ++cnt;
25     vis[u] = 1;
26     sta[top++] = u;
27     for(int i = 0; i < G[u].size();i ++)
28     {
29         int v = G[u][i];
30         if(!dfn[v])
31         {
32             tarjan(v);
33             low[u] = min(low[u],low[v]);
34         }
35         else if(vis[v])
36         {
37             low[u] = min(low[u],dfn[v]);
38         }
39     }
40     if(dfn[u] == low[u])
41     {
42         int t;
43         ++scc;
44         do
45         {
46             t = sta[--top];
47             vis[t] = 0;
48             belong[t] = scc;
49         }while(t != u);
50     }
51 }
52 int main()
53 {
54     scanf("%d%d",&n,&m);
55     init();
56     for(int i = 0;i < m;i ++)
57     {
58         scanf("%d%d",&S[i],&T[i]);
59         if(S[i] > T[i]) swap(S[i],T[i]);
60     }
61     for(int i = 0;i < m;i ++)
62     {
63         for(int j = i + 1;j < m;j++)
64         {
65             if(S[i] < S[j] && S[j] < T[i] && T[i] < T[j]||S[j] < S[i] && S[i] < T[j] && T[j] < T[i])
66             {
67                 add(i,j + m);
68                 add(j + m,i);
69                 add(j,i + m);
70                 add(i + m,j);
71             }
72         }
73     }
74     for(int i = 0; i < (m<<1);i ++)
75     {
76         if(!dfn[i]) tarjan(i);
77     }
78     for(int i = 0;i < m;i ++)
79     {
80         if(belong[i] == belong[i+m])
81         {
82             printf("the evil panda is lying again
");
83             return 0;
84         }
85     }
86     printf("panda is telling the truth...
");
87     return 0;
88  } 
原文地址:https://www.cnblogs.com/Mingusu/p/12548874.html