Ikki’s Story IV - Panda’s Trick
题目大意:
一个圆上按顺时针编号
0
−
n
−
1
0-n-1
0−n−1,要连接
m
m
m对点要求连线要么在圆内,要么在圆外。(不能穿过圆弧)
问所有线可否不相交。
思路:
2
−
s
a
t
2-sat
2−sat问题建立模型很重要。
在二维平面下判断两直线相交:假如一条直线的两点在另一条直线的两端时必相交。
通过这个条件可以确定如果两线段相交,必不同侧。
其他条件不能确定出必要关系。
无向图并查集即可。
Code:
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
//#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
#define PI 3.1415926535898
using namespace std;
const int N=2e3+10;
int n,m;
pair<int,int> pa[N];
int flag[N];
void init(){
for(int i=0;i<=n*2;i++){
flag[i]=i;
}
}
int find(int x){
if(flag[x]==x){
return x;
}
else{
return flag[x]=find(flag[x]);
}
}
void work(int x,int y){
int s1=find(x),s2=find(y);
flag[s1]=flag[s2];
}
bool ok(int x1,int y1,int x2,int y2){
if(x1>x2){
swap(x1,x2),swap(y1,y2);
}
if(x2>=x1&&x2<=y1&&y2>=y1){
return 1;
}
return 0;
}
bool ok(){
init();
for(int i=1;i<=m;i++){
for(int j=i+1;j<=m;j++){
if(ok(pa[i].first,pa[i].second,pa[j].first,pa[j].second)){
work(i,j+n);
work(j,i+n);
}
}
}
for(int i=0;i<=n;i++){
if(find(i)==find(i+n)) return 0;
}
return 1;
}
int main(){
guo312;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>pa[i].first>>pa[i].second;
if(pa[i].first>pa[i].second){
swap(pa[i].first,pa[i].second);
}
}
if(ok()){
cout<<"panda is telling the truth...";
}
else{
cout<<"the evil panda is lying again";
}
return 0;
}