题意:
圆上n个点,m对点之间连边,连在园内或园外,所有边不相交是否可行
发现两对点连线都在内相交则都在外也相交,那么只有一个在内一个在外啦,转化为$2-SAT$问题
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int N=1005,M=5e5; typedef long long ll; inline int read(){ char c=getchar();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } int n,m,a[N],b[N]; struct edge{ int v,ne; }e[M]; int h[N],cnt=0; inline void ins(int u,int v){ cnt++; e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt; } void buildGraph(){ for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) if((a[i]<a[j]&&a[j]<b[i]&&b[i]<b[j])||(a[j]<a[i]&&a[i]<b[j]&&b[j]<b[i])){ int x=i<<1,y=j<<1; ins(x,y-1);ins(y-1,x); ins(x-1,y);ins(y,x-1); } } int dfn[N],low[N],dfc,belong[N],scc; int st[N],top; void dfs(int u){ dfn[u]=low[u]=++dfc; st[++top]=u; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(!dfn[v]){ dfs(v); low[u]=min(low[u],low[v]); }else if(!belong[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ scc++; while(true){ int x=st[top--]; belong[x]=scc; if(x==u) break; } } } bool judge(){ for(int i=1;i<=m;i++) if(belong[i<<1]==belong[(i<<1)-1]) return false; return true; } int main(){ freopen("in","r",stdin); n=read();m=read(); for(int i=1;i<=m;i++){ a[i]=read(),b[i]=read(); if(a[i]>b[i]) swap(a[i],b[i]); } buildGraph(); int _=m<<1; for(int i=1;i<=_;i++) if(!dfn[i]) dfs(i); if(judge()) puts("panda is telling the truth..."); else puts("the evil panda is lying again"); }
POJ Ikki's Story IV - Panda's Trick [2-SAT]
时间: 2024-11-25 04:53:19