[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

 

posted @ 2016-06-28 09:19  czllgzmzl  阅读(195)  评论(0编辑  收藏  举报