题意:一个圈,在圈上连点,可以从内侧连,也可以从外侧连,问是否可以全部没有交叉。
思路:所有线要么在内侧,要么在外侧。要想没有交叉,那么建造在同一侧会交叉的线一定不能在同一侧,建图转化成一个2-sat问题。判断是否所有边符合条件即可。
下面附上2-sat代码。
其实染色判断二分图的方法也可以做,也附上代码。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int m,n,ans;
int fst[1005],next[550005],node[550005];
int en,a[1005],b[1005],cnt,s[1005];
bool vis[1005];
void init()
{
ans=0;
en=0;
memset(fst,-1,sizeof(fst));
memset(vis,0,sizeof(vis));
}
bool can(int i,int j)
{
if(a[i]<=a[j]&&b[i]<=a[j])return false;
else if(a[j]<=a[i]&&b[j]<=a[i])return false;
else if(a[i]>=a[j]&&b[i]<=b[j])return false;
else if(a[j]>=a[i]&&b[j]<=b[i])return false;
return true;
}
void add(int u,int v)
{
next[en]=fst[u];
fst[u]=en;
node[en]=v;
en++;
}
bool dfs(int x)
{
if(vis[x^1])return false;
if(vis[x])return true;
vis[x]=1;
s[cnt++]=x;
for(int i=fst[x];i!=-1;i=next[i])
{
int v=node[i];
if(!dfs(v))return false;
}
return true;
}
void twosat()
{
for(int i=0;i<n;i++)
{
if(!vis[2*i]&&!vis[2*i+1])
{
cnt=0;
if(!dfs(2*i))
{
while(cnt>0)vis[s[--cnt]]=0;
if(!dfs(2*i+1))
{
ans=1;
break;
}
}
}
}
if(ans)cout<<"the evil panda is lying again"<<endl;
else cout<<"panda is telling the truth..."<<endl;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
init();
for(int i=0;i<n;i++)
{
scanf("%d%d",&a[i],&b[i]);
if(a[i]>b[i])swap(a[i],b[i]);
for(int j=i-1;j>=0;j--)
{
if(can(i,j))
{
add(2*i,2*j+1);
add(2*i+1,2*j);
}
}
}
twosat();
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int m,n,ans;
int fst[505],next[250005],node[250005];
int en,a[505],b[505];
bool vis[505],f[505];
void init()
{
ans=0;
en=0;
memset(fst,-1,sizeof(fst));
memset(vis,0,sizeof(vis));
}
bool can(int i,int j)
{
if(a[i]<=a[j]&&b[i]<=a[j])return false;
else if(a[j]<=a[i]&&b[j]<=a[i])return false;
else if(a[i]>=a[j]&&b[i]<=b[j])return false;
else if(a[j]>=a[i]&&b[j]<=b[i])return false;
return true;
}
void add(int u,int v)
{
next[en]=fst[u];
fst[u]=en;
node[en]=v;
en++;
next[en]=fst[v];
fst[v]=en;
node[en]=u;
en++;
}
void bfs(int k)
{
queue<int>q;
q.push(k);
vis[k]=1;
f[k]=true;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=fst[u];i!=-1;i=next[i])
{
int v=node[i];
if(!vis[v])
{
f[v]=!f[u];
vis[v]=1;
q.push(v);
}
else
{
if(f[u]==f[v])
{
ans=1;
return;
}
}
}
}
}
void solve()
{
for(int i=0;i<n;i++)
{
if(!vis[i])bfs(i);
if(ans)break;
}
if(ans)cout<<"the evil panda is lying again"<<endl;
else cout<<"panda is telling the truth..."<<endl;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
init();
for(int i=0;i<n;i++)
{
scanf("%d%d",&a[i],&b[i]);
if(a[i]>b[i])swap(a[i],b[i]);
for(int j=i-1;j>=0;j--)
{
if(can(i,j))add(i,j);
}
}
solve();
}
return 0;
}