poj3207 Ikki's Story IV - Panda's Trick
我们想,倘若有两个曲线u v,他们不能共存,那么连边一定是:
- u->v'
- u'->v
- v'->u
- v->u'
其中x代表x边在内侧(外侧),x'代表x边在外侧(内侧)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n, m, dfn[1005], sta[1005], din, loo[1005], ind, scc, bel[1005];
int hea[1005], cnt;
bool ins[1005];
struct Edge{
int too, nxt;
}edge[1000005];
struct Line{
int uu, vv;
}nd[1005];
void add_edge(int fro, int too){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
hea[fro] = cnt;
}
void tarjan(int u){
dfn[u] = loo[u] = ++ind;
sta[++din] = u;
ins[u] = true;
for(int i=hea[u]; i; i=edge[i].nxt){
int t=edge[i].too;
if(!dfn[t]){
tarjan(t);
loo[u] = min(loo[u], loo[t]);
}
else if(ins[t]) loo[u] = min(loo[u], dfn[t]);
}
int j;
if(dfn[u]==loo[u]){
scc++;
do{
j = sta[din--];
ins[j] = false;
bel[j] = scc;
}while(dfn[j]!=loo[j]);
}
}
int main(){
cin>>n>>m;
for(int i=0; i<m; i++){
scanf("%d %d", &nd[i].uu, &nd[i].vv);
if(nd[i].uu>nd[i].vv) swap(nd[i].uu, nd[i].vv);
}
for(int i=0; i<m; i++)
for(int j=i+1; j<m; j++)
if((nd[j].uu>nd[i].uu && nd[j].uu<nd[i].vv && nd[j].vv>nd[i].vv) || (nd[i].uu>nd[j].uu && nd[i].uu<nd[j].vv && nd[i].vv>nd[j].vv)){
add_edge(i+i, j+j+1);
add_edge(j+j, i+i+1);
add_edge(j+j+1, i+i);
add_edge(i+i+1, j+j);
}
for(int i=0; i<m+m; i++)
if(!dfn[i])
tarjan(i);
for(int i=0; i<m+m; i+=2)
if(bel[i]==bel[i|1]){
printf("the evil panda is lying again\n");
return 0;
}
printf("panda is telling the truth...\n");
return 0;
}
拙いものと思えども、
その手に握る其れこそが、
いつか幻想を生んでいく。