题解:
2-sat
这次不是按照点来见图,而是按照遍
xi表示i号边在元内部,xi+m表示i在圆外部
然后判断一下两边在圆内圆外是否相交
代码:
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; const int N=2005; int flag[N],x[N],y[N],n,ne[N*N],fi[N],zz[N*N],num; int t,zhan[N],dfn[N],m,l,ans,low[N],an[N]; void jb(int x,int y) { ne[++num]=fi[x]; fi[x]=num; zz[num]=y; } void dfs(int x) { low[x]=dfn[x]=++l; zhan[++t]=x; flag[x]=true; for (int i=fi[x];i!=0;i=ne[i]) { if (an[zz[i]])continue; if(!dfn[zz[i]])dfs(zz[i]); if(!flag[zz[i]])low[x]=min(low[x],dfn[zz[i]]);else low[x]=min(low[x],low[zz[i]]); } if (dfn[x]==low[x]) { ans++; while (zhan[t]!=x) { flag[zhan[t]]=false; an[zhan[t--]]=ans; } an[zhan[t--]]=ans; flag[x]=false; } } int main() { scanf("%d%d",&n,&m); for (int i=0;i<m;i++) { scanf("%d%d",&x[i],&y[i]); if (x[i]>y[i])swap(x[i],y[i]); } for (int i=0;i<m;i++) for (int j=i+1;j<m;j++) if (x[j]>=x[i]&&x[j]<=y[i]&&y[j]>=y[i] ||y[j]>=x[i]&&y[j]<=y[i]&&x[j]<=x[i]) { jb(i,j+m); jb(i+m,j); jb(j+m,i); jb(j,i+m); } for (int i=0;i<2*m;i++) if (!dfn[i])dfs(i); for (int i=0;i<m;i++) if (an[i]==an[i+m]) { puts("the evil panda is lying again"); return 0; } puts("panda is telling the truth..."); }