BZOJ1997 [Hnoi2010]Planar (2-sat)
题意:给你一个哈密顿图,判断是不是平面图
思路:先找出哈密顿图来。哈密顿回路可以看成一个环,把边集划分成两个集合,一个在环内,一个在外。如果有两条相交边在环内,则一定不是平面图,所以默认两条相交边,转化成2——sat,两条边不能同时在内或外,注意双向加边。(以边来转化成两倍)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<queue> 5 #include<stack> 6 #include<bits/stdc++.h> 7 using namespace std; 8 #define LL long long 9 #define clc(a,b) memset(a,b,sizeof(a)) 10 const int maxn = 2000 + 10; 11 int r(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 int T,n,m,ind,top,cnt,scc; 18 int u[10005],v[10005]; 19 int c[2010],pos[2005]; 20 int last[2005],dfn[2005],low[2005],q[2005],bl[2005]; 21 bool inq[2005]; 22 23 struct edge{ 24 int to,next; 25 }e[1000005]; 26 27 void add(int u,int v){ 28 e[++cnt].to=v; 29 e[cnt].next=last[u]; 30 last[u]=cnt; 31 } 32 33 void tarjan(int x){ 34 inq[x]=1;q[++top]=x; 35 low[x]=dfn[x]=++ind; 36 for(int i=last[x];i;i=e[i].next) 37 if(!dfn[e[i].to]) 38 tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]); 39 else if(inq[e[i].to]) 40 low[x]=min(low[x],dfn[e[i].to]); 41 int now=-1; 42 if(low[x]==dfn[x]) 43 { 44 scc++; 45 while(now!=x) 46 { 47 now=q[top--];inq[now]=0; 48 bl[now]=scc; 49 } 50 } 51 } 52 53 bool jude(){ 54 for(int i=1;i<=m;i++){ 55 if(bl[i*2]==bl[i*2-1]) 56 return false; 57 } 58 return true; 59 } 60 int main(){ 61 T=r(); 62 while(T--){ 63 n=r(),m=r(); 64 for(int i=1;i<=m;i++){ 65 u[i]=r();v[i]=r(); 66 } 67 clc(last,0); 68 cnt=0; 69 scc=ind=0; 70 clc(low,0); 71 clc(dfn,0); 72 for(int i=1;i<=n;i++) 73 c[i]=r(); 74 if(m>3*n-6){ 75 printf("NO\n"); 76 continue; 77 } 78 for(int i=1;i<=n;i++) 79 pos[c[i]]=i; 80 top=0; 81 for(int i=1;i<=m;i++){ 82 u[i]=pos[u[i]],v[i]=pos[v[i]]; 83 if(u[i]>v[i]) swap(u[i],v[i]); 84 if(v[i]-u[i]==1||v[i]-u[i]==n-1) continue; 85 u[++top]=u[i],v[top]=v[i]; 86 } 87 m=top; 88 for(int i=1;i<=m;i++){ 89 for(int j=i+1;j<=m;j++){ 90 if((u[i]<u[j]&&v[i]>u[j]&&v[i]<v[j])||(u[i]>u[j]&&v[j]>u[i]&&v[i]>v[j])){ 91 add(2*i-1,2*j); 92 add(2*i,2*j-1); 93 add(2*j-1,2*i); 94 add(2*j,2*i-1); 95 } 96 } 97 } 98 for(int i=1;i<=2*m;i++){ 99 if(dfn[i]==0){ 100 tarjan(i); 101 } 102 } 103 if(jude()) printf("YES\n"); 104 else printf("NO\n"); 105 106 } 107 return 0; 108 }