标签:
题意:平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,使这些边都不相交。
算比较裸的题目了,关键找到如何判断两对点交不交叉的关系就好
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1100;
vector<int> g[N];
struct node
{
int x,y;
}pir[N];
int n,m;
inline void add_edge(int u,int v)
{
g[u].push_back(v);
}
int dfn[N],low[N],tmp[N],sta[N],top;
int index;
void ini()
{
for(int i=0;i<=2*m;i++) g[i].clear();
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(tmp,0,sizeof(tmp));
top=index=0;
}
void tarjan(int u)
{
low[u]=dfn[u]=++index;
tmp[u]=1;
sta[++top]=u;
int sz=g[u].size();
for(int i=0;i<sz;i++)
{
int v=g[u][i];
if(tmp[v]==0) tarjan(v);
if(tmp[v]==1) low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u])
{
int v;
do
{
v=sta[top--];
tmp[v]=2;
low[v]=low[u];
}while(v!=u);
}
}
bool ok()
{
for(int i=0;i<2*m;i++)
if(low[i]==low[i^1]) return false;
return true;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
ini();
for(int i=0;i<m;i++)
{
scanf("%d%d",&pir[i].x,&pir[i].y);
}
for(int i=0;i<m;i++)
for(int j=i+1;j<m;j++)
{
int u=i*2,v=j*2;
bool f1=( pir[i].x<max(pir[j].x,pir[j].y)&&pir[i].x>min(pir[j].x,pir[j].y) );
bool f2=( pir[i].y<max(pir[j].x,pir[j].y)&&pir[i].y>min(pir[j].x,pir[j].y) );
if(f1^f2)//两点对交叉
{
add_edge(u,v^1);
add_edge(v,u^1);
add_edge(u^1,v);
add_edge(v^1,u);
}
}
for(int i=0;i<2*m;i++)
if(dfn[i]==0) tarjan(i);
if(ok()) puts("panda is telling the truth...");
else puts("the evil panda is lying again");
}
return 0;
}
POJ 3207 Ikki's Story IV - Panda's Trick(2-sat判解存在性)
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/45693587