[HNOI2010]PLANAR

题解:

  首先判断m的大小,如果m>3*n-6,则一定没有平面图. 然后我们先将环扣出来,我们发现对于环上的两条边有交的话,那么这两条边就不能在环的同侧,所以我们就可以将边看作点,判断是否是二分图即可,连边由于m<=3*n-6,所以我们暴力连边就行了.

 

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<cstring>
  7 #include<queue>
  8 #include<vector>
  9 #include<stack>
 10 #include<map>
 11 #define RG register
 12 #define MAXN 500010
 13 #define LL long long int
 14 using namespace std;
 15 const int INF=1e9;
 16 const int mod=19650827;
 17 struct node{
 18   int next;
 19   int to;
 20 }t[MAXN];
 21 int head[MAXN],num;
 22 int L[MAXN],R[MAXN],v[MAXN];
 23 int T;
 24 int n,m;
 25 int used[210][210];
 26 int id[MAXN];
 27 int w[MAXN],tot;
 28 int color[MAXN],vis[MAXN];
 29 void add(int from,int to)
 30 {
 31   t[++num].next=head[from];
 32   t[num].to=to;
 33   head[from]=num;
 34 }
 35 bool check(int a,int b,int c,int d)
 36 {
 37   if((c<=a || c>=b)&&(d>=a&&d<=b)) return true;
 38   if((d<=a || d>=b)&&(c>=a&&c<=b)) return true;
 39   return false;
 40 }
 41 void init()
 42 {
 43   memset(w,0,sizeof(w));
 44   memset(head,0,sizeof(head));num=0;
 45   for(int i=1;i<=m;i++)
 46     {
 47       int a=id[L[i]],b=id[R[i]];
 48       if(a>b) swap(a,b);
 49       if(used[a][b]) continue;
 50       for(int j=i+1;j<=m;j++)
 51     {
 52       int c=id[L[j]],d=id[R[j]];
 53       if(c>d) swap(c,d);
 54       if(used[c][d]) continue;
 55       if(a==c || a==d || b==c || b==d) continue;
 56       if(!check(a,b,c,d)) continue;
 57       if(!w[i]) w[i]=++tot;if(!w[j]) w[j]=++tot;
 58       add(w[i],w[j]);add(w[j],w[i]);
 59     }
 60     }
 61 }
 62 bool dfs(int u)
 63 {
 64   vis[u]=1;
 65   for(int i=head[u];i;i=t[i].next)
 66     {
 67       int v=t[i].to;
 68       if(!vis[v]){
 69     color[v]=color[u]^1;
 70     if(!dfs(v)) return false;
 71       }
 72       else if(color[u]==color[v]) return false;
 73     }
 74   return true;
 75 }
 76 void work()
 77 {
 78   memset(vis,0,sizeof(vis));
 79   memset(color,0,sizeof(color));
 80   int flag=1;
 81   for(int i=1;i<=tot;i++)
 82     if(!vis[i]){
 83       if(!dfs(i)){
 84     flag=0;break;
 85       }
 86     }
 87   if(flag) printf("YES");
 88   else printf("NO");
 89 }
 90 int main()
 91 {
 92   freopen("1.in","r" ,stdin);
 93   scanf("%d",&T);
 94   for(int z=1;z<=T;z++)
 95     {
 96       scanf("%d%d",&n,&m);
 97       for(int i=1;i<=m;i++) scanf("%d%d",&L[i],&R[i]);
 98       memset(used,0,sizeof(used));
 99       for(int i=1;i<=n;i++){
100     scanf("%d",&v[i]);
101     id[v[i]]=i;used[i][i-1]=used[i-1][i]=1;
102       }
103       used[n][1]=used[1][n]=1;
104       if(m>3*n-6) {printf("NO");if(z<T) printf("\n");continue;}
105       init();work();if(z<T) printf("\n");
106     }
107   return 0;
108 }

 

posted @ 2017-12-21 17:42  楼主大大  阅读(188)  评论(0编辑  收藏  举报