这题读起来有点蛋疼,真是英语害死人!
题意是有n个点在圆的边缘,编号是0~n-1顺时针,有m条线(不一定是直线,线可以再圆内,也可以再圆外),问是否存在所有线不想交的情况
方法:2-SAT,以所有线为点,两两枚举,假设i代表在圆内,i'代表圆外,如果线i与线j在圆内相交,就连i---j'还有j---i',注意要连双向边,然后就套模板,如果两个矛盾点在同一个强连通分量里就false。
#define N 1111
vector<int> v[N];
stack<int> s;
bool vis[N];
bool inStack[N];
int low[N],dfn[N];
int belong[N];//属于哪个强连通分量
int n,m,step,t;
struct node{
int s,t;
}p[N];
void init(){
int i;
for(i=0;i<=2*n;i++){
v[i].clear();
vis[i] = 0;
inStack[i] = 0;
}
while(!s.empty())s.pop();
}
void add(int a,int b){
v[a].push_back(b);
}
//tarjan缩点
void tarjan(int u){
vis[u]=true;
step++;
s.push(u);
inStack[u]=true;
low[u]=step,dfn[u]=step;
int i,j;
for(i=0;i<v[u].size();i++)
{
int x=v[u][i];
if(!vis[x])
{
tarjan(x);
low[u]=min(low[u],low[x]);
}
else
if(inStack[x])
low[u]=min(low[u],dfn[x]);
}
if(low[u]==dfn[u])
{
t++;
while(1)
{
int x=s.top();
s.pop();
belong[x]=t;
inStack[x]=false;
if(x==u)break;
}
}
}
void solve(){
t = 0,step = 0;
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if((p[i].s < p[j].s && p[i].t < p[j].t && p[i].t > p[j].s) || (p[i].s > p[j].s && p[i].t > p[j].t && p[i].s < p[j].t)){
add(i,j+n);
add(j+n,i);
add(j,i+n);
add(i+n,j);
}
}
}
for(i=0;i<2*n;i++){
if(!vis[i])tarjan(i);
}
for(i=0;i<n;i++){
if(belong[i] == belong[i+n]){
puts("the evil panda is lying again");
return ;
}
}
puts("panda is telling the truth...");
}
int main(){
while(scanf("%d%d",&m,&n) != -1){
int i;
init();
for(i=0;i<n;i++){
scanf("%d%d",&p[i].s,&p[i].t);
if(p[i].s > p[i].t)swap(p[i].s,p[i].t);
}
solve();
}
return 0;
}