题目链接:https://vjudge.net/problem/POJ-3207
题目意思:有一个圆,给出一些边连接着两个点,边可以从圆里连,也可以从圆外连,问是否可以不相交
对于边i,ji,j限制条件为不相交,即不在同一个集合中
因此我们将这个问题转化为了2-SAT问题
设ii表示边ii在圆内,i′i′表示ii在圆外
若(i,j)(i,j)在圆内相交,那么它们在圆外也一定相交
如果边i,ji,j在圆内相交
那么就从ii连向j′j′(i内j外),从j′j′连向ii(i内j外),从jj连向i′i′(j内i外),从i′i′连向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 }