首先用一波神奇的操作,平面图边数m<=3*n-6,直接把m降到n,
然后对于冲突的边一条环内,一条环外,可以用并查集或者2Sat做,
当然并查集是无向的,2Sat是有向的,显然用并查集比较好 复杂度大概是O(T*n*n)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstring> 5 #define pb push_back 6 #define pii pair<int,int> 7 #define ft first 8 #define sc second 9 #define MAXN 200000+10 10 using namespace std; 11 int n,m; 12 int b[MAXN],d[MAXN],f[MAXN]; 13 pii E[MAXN]; 14 int find(int x){return (f[x]==x?x:f[x]=find(f[x]));} 15 void init_find(){ 16 for(int i=1;i<=(m<<1);i++)f[i]=i; 17 } 18 void lik(int x,int y){ 19 x=find(x),y=find(y); 20 if(x!=y)f[x]=y; 21 } 22 int solve(){ 23 scanf("%d%d",&n,&m); 24 init_find(); 25 for(int i=1;i<=m;i++)scanf("%d%d",&E[i].ft,&E[i].sc); 26 int t; 27 for(int i=1;i<=n;i++)scanf("%d",&t),d[t]=i; 28 if(m>3*n-6)return 0; 29 memset(b,0,sizeof(b)); 30 for(int i=1;i<=m;i++){ 31 E[i].ft=d[E[i].ft],E[i].sc=d[E[i].sc]; 32 if(E[i].ft>E[i].sc){swap(E[i].ft,E[i].sc);} 33 if(E[i].sc-E[i].ft==1||E[i].sc-E[i].ft==n-1)b[i]=1; 34 } 35 pii x,y; 36 for(int i=1;i<=m;i++){ 37 if(b[i])continue; 38 for(int j=i+1;j<=m;j++){ 39 if(b[j])continue; 40 x=E[i],y=E[j]; 41 if(x.ft==y.ft||x.ft==y.sc)continue; 42 if(x.sc==y.ft||x.sc==y.sc)continue; 43 if(x.ft==x.sc||y.ft==y.sc)continue; 44 if(x.ft>y.ft)swap(x,y); 45 if(y.ft<x.sc&&x.sc<y.sc){ 46 if(find(i)==find(j))return 0; 47 lik(i,j+m),lik(j,i+m); 48 } 49 } 50 } 51 return 1; 52 } 53 int main() 54 { 55 // freopen("data.in","r",stdin); 56 int T; 57 scanf("%d",&T); 58 while(T--){ 59 if(solve())printf("YES\n"); 60 else printf("NO\n"); 61 } 62 return 0; 63 }