poj 3207(2-SAT+SCC)

传送门:Problem 3207

https://www.cnblogs.com/violet-acmer/p/9769406.html

难点:

  题意理解。

题意:

  平面上有一个圆,圆上有n个点(分别编号0-n-1,按顺序在圆上排列),现在要对这n个点连接m条线,这m条线的两个端点已经给出了,这个线可以从圆内连或从圆外连,且任意一个点最多只作为一条线的端点.要求任意两条线不相交,问你是否可能?

  注意:两点间的连线没说一定是直线。

题解:

  两直线ab,cd(a < b , c < d)不可以同时在圆内或圆外的条件是 a<c<b<d || c<a<d<b

  以此构造布尔方程。

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 using namespace std;
 6 #define pb push_back
 7 #define mem(a,b) (memset(a,b,sizeof a))
 8 const int maxn=500+50;
 9 
10 int n,m;
11 int a[maxn],b[maxn];
12 int scc[2*maxn];
13 bool vis[2*maxn];
14 vector<int >vs;
15 vector<int >G[2*maxn],rG[2*maxn];
16 void addEdge(int u,int v)
17 {
18     G[u].pb(v);
19     rG[v].pb(u);
20 }
21 bool Touch(int a,int b,int c,int d)//判断 ab 是否一定与 cd 相交
22 {
23     if(a<c && c<b && b<d)
24         return true;
25     if(c<a && a<d && d<b)
26         return true;
27     return false;
28 }
29 void Dfs(int u)
30 {
31     vis[u]=true;
32     for(int i=0;i < G[u].size();++i)
33     {
34         int to=G[u][i];
35         if(!vis[to])
36             Dfs(to);
37     }
38     vs.pb(u);
39 }
40 void rDfs(int u,int k)
41 {
42     vis[u]=true;
43     scc[u]=k;
44     for(int i=0;i < rG[u].size();++i)
45     {
46         int to=rG[u][i];
47         if(!vis[to])
48             rDfs(to,k);
49     }
50 }
51 void SCC()
52 {
53     mem(vis,false);
54     vs.clear();
55     for(int i=1;i <= 2*m;++i)
56         if(!vis[i])
57             Dfs(i);
58     mem(vis,false);
59     int k=0;
60     for(int i=vs.size()-1;i >= 0;--i)
61     {
62         int to=vs[i];
63         if(!vis[to])
64             rDfs(to,++k);
65     }
66 }
67 int main()
68 {
69     scanf("%d%d",&n,&m);
70     for(int i=1;i <= m;++i)
71     {
72         scanf("%d%d",a+i,b+i);
73         if(a[i] > b[i])
74             swap(a[i],b[i]);
75         for(int j=1;j < i;++j)
76         {
77             if(Touch(a[i],b[i],a[j],b[j]))
78             {
79                 addEdge(j+m,i);
80                 addEdge(i+m,j);
81                 addEdge(j,i+m);
82                 addEdge(i,j+m);
83             }
84         }
85     }
86     SCC();
87     bool flag=false;
88     for(int i=1;i <= m;++i)
89         if(scc[i] == scc[i+m])
90             flag=true;
91     if(flag)
92         printf("the evil panda is lying again\n");
93     else
94         printf("panda is telling the truth...\n");
95 }
View Code

 

posted @ 2018-10-11 21:44  HHHyacinth  阅读(212)  评论(0编辑  收藏  举报