P3209 [HNOI2010] 平面图判定 题解
由于题目已经给定一条哈密顿回路,因此 $ n $ 个点在平面上恰好会形成一个圈,每条额外的边可以在圈内或圈外。两个相交的额外边显然不能在同一侧,因此可以转化为二分图判定,把额外边视为点,如果两个额外边在原图中相交则连边。注意直接跑会超时,但是发现题目中的数据范围是假的,平面图有一个性质,满足如果是平面图边数一定不会超过 $ 3n-6 $,其中 $ n $ 是点数。
代码:
#include<bits/stdc++.h>
#define time(null) chrono::steady_clock::now().time_since_epoch().count()
#define int long long
#define uint unsigned long long
#define debug() cout<<"come here\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define pb push_back
#define Code return
#define by 0
#define MCYYDS ;
using namespace std;
int qpow(int a,int b,int p=INF){int ret=1;while(b){if(b&1)ret=(ret*a)%p;a=(a*a)%p;b>>=1;}return ret;}
inline int read(){int ret=0,f=1;char ch=getchar();while(ch<'0'||ch>'9')f=(ch=='-'?-1:f),ch=getchar();while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();return ret*f;}
inline void write(int x){if(x<0){putchar('-');write(-x);return ;}if(x>9)write(x/10);putchar((char)(x%10+48));}
inline void writech(int x,char ch){write(x);putchar(ch);}
vector<int> e[705];
int col[705];
bool dfs(int u,int c)
{
col[u]=c;
for(auto v:e[u])
{
if(col[v]==c)return 0;
if(col[v]==0&&!dfs(v,c^1))return 0;
}
return 1;
}
bool check(int x1,int y1,int x2,int y2)
{
return (x1<x2&&x2<y1&&y1<y2)||(x2<x1&&x1<y2&&y2<y1);
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int T=read();
while(T--)
{
int n=read(),m=read();
vector<int> f(m+1,0),t(m+1,0),g(n+1,0);
bool flag=0;
memset(col,0,sizeof(col));
for(int i=1;i<=3*n-6;i++)
{
e[i].clear();
}
for(int i=1;i<=m;i++)
{
f[i]=read(),t[i]=read();
}
for(int i=1;i<=n;i++)
{
int x=read();
g[x]=i;
}
if(m>3*n-6)
{
puts("NO");
continue;
}
for(int i=1;i<m;i++)
{
for(int j=i+1;j<=m;j++)
{
int x1=g[f[i]],x2=g[f[j]],y1=g[t[i]],y2=g[t[j]];
if(x1>y1)swap(x1,y1);
if(x2>y2)swap(x2,y2);
if(check(x1,y1,x2,y2))
{
e[i].pb(j);
e[j].pb(i);
}
}
}
for(int i=1;i<=m;i++)
{
if(!col[i])
{
if(!dfs(i,3))
{
flag=1;
break;
}
}
}
if(flag)puts("NO");
else puts("YES");
}
Code by MCYYDS
}

浙公网安备 33010602011771号