[bzoj1997] [Hnoi2010]Planar

本文介绍了一种平面图判定的方法,通过判断非环边是否能够做到不相交来确定图是否为平面图。提供了多种实现方式,包括使用并查集、二分图判断等,并利用平面图的边数特性进行剪枝优化。

  平面图判定。。好高大上的东西。。

  然而题目保证有个n元环= =。。。所以只要判断一下,非环边能否做到不相交。

  

  接下来有各种姿势。。。

  可以将边看成点,不能放在环的同一侧(会相交)的边之间连边,判断新图是否为二分图(没有奇环);

  还可以上2-sat。。。。

  或者可以用并查集...其实就是因为这题2-sat的边是双向的。。所以直接并查集就好了;

  记得先用平面图m<=3*n-6的性质剪一下枝。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=1233;
 6 int u[10233],v[10233],id[maxn],fa[maxn];
 7 int i,j,k,n,m;
 8  
 9 int ra;char rx;
10 inline int read(){
11     rx=getchar(),ra=0;
12     while(rx<'0'||rx>'9')rx=getchar();
13     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
14 }
15 inline bool gg(int u1,int v1,int u2,int v2){
16     if(u1==u2||v1==v2||u1==v2||v1==u2)return 0;
17     u1=id[u1],v1=id[v1],u2=id[u2],v2=id[v2];
18     if(u1>v1)swap(u1,v1);if(u2>v2)swap(u2,v2);
19     if(u1>u2)swap(u1,u2),swap(v1,v2);
20     return !(u2>v1||v2<v1);
21 }
22 inline int getfa(int x){return fa[x]!=x?fa[x]=getfa(fa[x]):x;}
23 inline bool check(){
24     if(m>3*n-6)return 0;
25     register int j;int i,x,y;
26     for(i=1;i<=m+m;i++)fa[i]=i;
27     for(i=1;i<m;i++)for(j=i+1;j<=m;j++)if(gg(u[i],v[i],u[j],v[j])){
28         x=getfa(i),y=getfa(j);
29         if(x==y)return 0;
30         fa[x]=getfa(j+m),fa[y]=getfa(i+m);
31     }
32     return 1;
33 }
34 int main(){
35     for(int t=read();t;t--){
36         n=read(),m=read();
37         for(i=1;i<=m;i++)u[i]=read(),v[i]=read();
38         for(i=1;i<=n;i++)id[read()]=i;
39         puts(check()?"YES":"NO");
40     }
41 }
View Code

 

转载于:https://www.cnblogs.com/czllgzmzl/p/5622265.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值