[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 }