传送门
题意:一个圈,在圈上连点,可以从内侧连,也可以从外侧连,问是否可以全部没有交叉。
思路:所有线要么在内侧,要么在外侧。要想没有交叉,那么建造在同一侧会交叉的线一定不能在同一侧,建图转化成一个2-sat问题。判断是否所有边符合条件即可。
下面附上2-sat代码。
其实染色判断二分图的方法也可以做,也附上代码。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int m,n,ans; int fst[1005],next[550005],node[550005]; int en,a[1005],b[1005],cnt,s[1005]; bool vis[1005]; void init() { ans=0; en=0; memset(fst,-1,sizeof(fst)); memset(vis,0,sizeof(vis)); } bool can(int i,int j) { if(a[i]<=a[j]&&b[i]<=a[j])return false; else if(a[j]<=a[i]&&b[j]<=a[i])return false; else if(a[i]>=a[j]&&b[i]<=b[j])return false; else if(a[j]>=a[i]&&b[j]<=b[i])return false; return true; } void add(int u,int v) { next[en]=fst[u]; fst[u]=en; node[en]=v; en++; } bool dfs(int x) { if(vis[x^1])return false; if(vis[x])return true; vis[x]=1; s[cnt++]=x; for(int i=fst[x];i!=-1;i=next[i]) { int v=node[i]; if(!dfs(v))return false; } return true; } void twosat() { for(int i=0;i<n;i++) { if(!vis[2*i]&&!vis[2*i+1]) { cnt=0; if(!dfs(2*i)) { while(cnt>0)vis[s[--cnt]]=0; if(!dfs(2*i+1)) { ans=1; break; } } } } if(ans)cout<<"the evil panda is lying again"<<endl; else cout<<"panda is telling the truth..."<<endl; } int main() { while(scanf("%d%d",&m,&n)!=EOF) { init(); for(int i=0;i<n;i++) { scanf("%d%d",&a[i],&b[i]); if(a[i]>b[i])swap(a[i],b[i]); for(int j=i-1;j>=0;j--) { if(can(i,j)) { add(2*i,2*j+1); add(2*i+1,2*j); } } } twosat(); } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int m,n,ans; int fst[505],next[250005],node[250005]; int en,a[505],b[505]; bool vis[505],f[505]; void init() { ans=0; en=0; memset(fst,-1,sizeof(fst)); memset(vis,0,sizeof(vis)); } bool can(int i,int j) { if(a[i]<=a[j]&&b[i]<=a[j])return false; else if(a[j]<=a[i]&&b[j]<=a[i])return false; else if(a[i]>=a[j]&&b[i]<=b[j])return false; else if(a[j]>=a[i]&&b[j]<=b[i])return false; return true; } void add(int u,int v) { next[en]=fst[u]; fst[u]=en; node[en]=v; en++; next[en]=fst[v]; fst[v]=en; node[en]=u; en++; } void bfs(int k) { queue<int>q; q.push(k); vis[k]=1; f[k]=true; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=fst[u];i!=-1;i=next[i]) { int v=node[i]; if(!vis[v]) { f[v]=!f[u]; vis[v]=1; q.push(v); } else { if(f[u]==f[v]) { ans=1; return; } } } } } void solve() { for(int i=0;i<n;i++) { if(!vis[i])bfs(i); if(ans)break; } if(ans)cout<<"the evil panda is lying again"<<endl; else cout<<"panda is telling the truth..."<<endl; } int main() { while(scanf("%d%d",&m,&n)!=EOF) { init(); for(int i=0;i<n;i++) { scanf("%d%d",&a[i],&b[i]); if(a[i]>b[i])swap(a[i],b[i]); for(int j=i-1;j>=0;j--) { if(can(i,j))add(i,j); } } solve(); } return 0; }