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代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }