P3209 [HNOI2010] 平面图判定 题解

题目链接: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
}
posted @ 2026-07-14 11:20  MCYYDS  阅读(3)  评论(0)    收藏  举报