【题目】http://poj.org/problem?id=3207
【大意】在圆上取任意点两两连线,线都在圆内部或外部。问能否使这些线不交叉。
【思路】
【参考】https://blog.csdn.net/qq_30974369/article/details/73930235
【代码】
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int M=200005;
int n,m;
int linkx[M],linky[M];
int head[M];
class node
{
public:
int v,next;
};
node edge[M];
int ei;
int Stack[M],si;
int DFN[M],LOW[M],tot;
int inthestack[M];
int scc;
int belong[M];
void tarjan(int x)
{
Stack[++si]=x;
inthestack[x]=1;
DFN[x]=LOW[x]=++tot;
for(int i=head[x]; i!=-1; i=edge[i].next)
{
int& t=edge[i].v;
if(!DFN[t])
{
tarjan(t);
LOW[x]=min(LOW[x],LOW[t]);
}
else if(DFN[t]&&inthestack[t])
{
LOW[x]=min(LOW[x],DFN[t]);
}
}
if(DFN[x]==LOW[x])
{
scc++;
do
{
belong[Stack[si]]=scc;
inthestack[Stack[si]]=0;
si--;
}
while(x!=Stack[si+1]);
}
return;
}
void addedge(int u,int v)
{
edge[++ei].v=v;
edge[ei].next=head[u];
head[u]=ei;
return;
}
void init()
{
memset(head,-1,sizeof(head));
memset(inthestack,0,sizeof(inthestack));
memset(LOW,0,sizeof(LOW));
memset(DFN,0,sizeof(DFN));
scc=tot=ei=si=0;
return;
}
void makeedge()
{
for(int i=1; i<=m; i++)
{
for(int j=i+1; j<=m; j++)
{
if((linkx[i]<linkx[j]&&linky[i]>linkx[j]&&
linky[i]<linky[j])||
(linkx[j]<linkx[i]&&linky[j]>linkx[i]&&
linky[j]<linky[i])
)
{
addedge(i,j+m);
addedge(j+m,i);
addedge(i+m,j);
addedge(j,i+m);
}
}
}
}
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(a>b)
swap(a,b);
a++,b++;
linkx[i]=a,linky[i]=b;
}
makeedge();
for(int i=1; i<=2*m; ++i) //缩点
if(!DFN[i])
tarjan(i);
for(int i=1; i<=m; i++)
{
if(belong[i]==belong[i+m])
{
cout<<"the evil panda is lying again"<<endl;
return 0;
}
}
cout<<"panda is telling the truth..."<<endl;
return 0;
}