POJ 3207 Ikki's Story IV - Panda's Trick
思路
0表示圆内,1表示园外
如果两个线能相交,就必须不相同,就变成2-SAT问题了
建图后求解即可
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
int a[20000],b[20000];
int u[2000100],v[2000100],fir[2000100],nxt[2000100],cnt,low[2000100],dfn[2000100],dfs_clock,vis[2000100],scc_cnt,sccno[2000100],n,m,choose[2000100];
stack<int> S;
void addedge(int ui,int vi){
++cnt;
u[cnt]=ui;
v[cnt]=vi;
nxt[cnt]=fir[ui];
fir[ui]=cnt;
}
void tarjan(int u){
low[u]=dfn[u]=++dfs_clock;
S.push(u);
vis[u]=true;
for(int i=fir[u];i;i=nxt[i]){
if(!dfn[v[i]]){
tarjan(v[i]);
low[u]=min(low[u],low[v[i]]);
}
else if(vis[v[i]])
low[u]=min(low[u],low[v[i]]);
}
if(low[u]==dfn[u]){
scc_cnt++;
while(1){
int x=S.top();
S.pop();
vis[x]=false;
sccno[x]=scc_cnt;
if(x==u)
break;
}
}
}
void get_scc(void){
for(int i=1;i<=2*m;i++)
if(!dfn[i])
tarjan(i);
}
void add(int i,int a,int j,int b){
addedge(i+a*m,j+b*m);
addedge(j+b*m,i+a*m);
addedge(i+(a^1)*m,j+(b^1)*m);
addedge(j+(b^1)*m,i+(a^1)*m);
}
bool judge(int i,int j){
int xi=min(a[i],b[i]),yi=max(a[i],b[i]);
if(((xi<a[j]&&a[j]<yi)&&(b[j]<xi||b[j]>yi))||((xi<b[j]&&b[j]<yi)&&(a[j]<xi||a[j]>yi)))
return true;
return false;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d %d",&a[i],&b[i]);
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
if(i!=j)
if(judge(i,j)){
// printf("%d %d",i,j);
add(i,1,j,0);
}
get_scc();
int flag=true;
for(int i=1;i<=m;i++){
if(sccno[i]==sccno[i+m]){
flag=false;
break;
}
}
if(flag){
printf("panda is telling the truth...\n");
}
else{
printf("the evil panda is lying again\n");
}
return 0;
}