首先用一波神奇的操作,平面图边数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 }
并查集

相关文章: