1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define M 20005 5 #define N 2005 6 using namespace std; 7 int T,n,m,head[N],next[100*M],u[100*M],x[M],y[M],pos[N],cnt,tot,c[N],dfn[N],low[N],f[N],tim,t,z[M],sum,shu[M]; 8 void tarjan(int x) 9 { 10 f[x]=1;z[++t]=x; 11 low[x]=dfn[x]=++tim; 12 for(int i=head[x];i;i=next[i]) 13 if(!dfn[u[i]]) 14 tarjan(u[i]),low[x]=min(low[x],low[u[i]]); 15 else if(f[u[i]]) 16 low[x]=min(low[x],dfn[u[i]]); 17 int now=-1; 18 if(low[x]==dfn[x]) 19 { 20 sum++; 21 while(now!=x) 22 { 23 now=z[t--];f[now]=0; 24 shu[now]=sum; 25 } 26 } 27 } 28 void jia(int a1,int a2) 29 { 30 cnt++; 31 next[cnt]=head[a1]; 32 head[a1]=cnt; 33 u[cnt]=a2; 34 } 35 bool pan() 36 { 37 for(int i=1;i<=m;i++) 38 if(shu[2*i]==shu[2*i-1]) 39 return 0; 40 return 1; 41 } 42 int main() 43 { 44 scanf("%d",&T); 45 for(;T;T--) 46 { 47 scanf("%d%d",&n,&m); 48 for(int i=1;i<=m;i++) 49 scanf("%d%d",&x[i],&y[i]); 50 memset(head,0,sizeof(head)); 51 sum=cnt=tim=0; 52 memset(dfn,0,sizeof(dfn)); 53 memset(low,0,sizeof(low)); 54 for(int i=1;i<=n;i++) 55 scanf("%d",&c[i]); 56 if(m>3*n-6) 57 { 58 printf("NO\n"); 59 continue; 60 } 61 tot=0; 62 for(int i=1;i<=n;i++) 63 pos[c[i]]=i; 64 for(int i=1;i<=m;i++) 65 { 66 x[i]=pos[x[i]]; 67 y[i]=pos[y[i]]; 68 if(x[i]>y[i]) 69 swap(x[i],y[i]); 70 if(y[i]-x[i]==1||(y[i]==n&&x[i]==1)) 71 continue; 72 tot++; 73 x[tot]=x[i]; 74 y[tot]=y[i]; 75 } 76 m=tot; 77 for(int i=1;i<=m;i++) 78 for(int j=i+1;j<=m;j++) 79 if((x[i]<x[j]&&x[j]<y[i]&&y[i]<y[j])||(x[j]<x[i]&&x[i]<y[j]&&y[j]<y[i])) 80 { 81 jia(i*2,j*2-1); 82 jia(j*2-1,i*2); 83 jia(i*2-1,j*2); 84 jia(j*2,i*2-1); 85 } 86 for(int i=1;i<=2*m;i++) 87 if(!dfn[i]) 88 tarjan(i); 89 if(pan()) 90 printf("YES\n"); 91 else 92 printf("NO\n"); 93 } 94 return 0; 95 }
平面图在环内顶多有n-3条,环外顶多有n-3条,环上n条,所以超过3*n-6条边一定不是平面图,然后把所有的边按哈密尔顿重新编号,判断是否相交,相交的话一定一条在外,一条在内,
这样就变成了2-set问题,用tarjin跑。