平面图判定。。好高大上的东西。。
然而题目保证有个n元环= =。。。所以只要判断一下,非环边能否做到不相交。
接下来有各种姿势。。。
可以将边看成点,不能放在环的同一侧(会相交)的边之间连边,判断新图是否为二分图(没有奇环);
还可以上2-sat。。。。
或者可以用并查集...其实就是因为这题2-sat的边是双向的。。所以直接并查集就好了;
记得先用平面图m<=3*n-6的性质剪一下枝。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=1233; 6 int u[10233],v[10233],id[maxn],fa[maxn]; 7 int i,j,k,n,m; 8 9 int ra;char rx; 10 inline int read(){ 11 rx=getchar(),ra=0; 12 while(rx<'0'||rx>'9')rx=getchar(); 13 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 14 } 15 inline bool gg(int u1,int v1,int u2,int v2){ 16 if(u1==u2||v1==v2||u1==v2||v1==u2)return 0; 17 u1=id[u1],v1=id[v1],u2=id[u2],v2=id[v2]; 18 if(u1>v1)swap(u1,v1);if(u2>v2)swap(u2,v2); 19 if(u1>u2)swap(u1,u2),swap(v1,v2); 20 return !(u2>v1||v2<v1); 21 } 22 inline int getfa(int x){return fa[x]!=x?fa[x]=getfa(fa[x]):x;} 23 inline bool check(){ 24 if(m>3*n-6)return 0; 25 register int j;int i,x,y; 26 for(i=1;i<=m+m;i++)fa[i]=i; 27 for(i=1;i<m;i++)for(j=i+1;j<=m;j++)if(gg(u[i],v[i],u[j],v[j])){ 28 x=getfa(i),y=getfa(j); 29 if(x==y)return 0; 30 fa[x]=getfa(j+m),fa[y]=getfa(i+m); 31 } 32 return 1; 33 } 34 int main(){ 35 for(int t=read();t;t--){ 36 n=read(),m=read(); 37 for(i=1;i<=m;i++)u[i]=read(),v[i]=read(); 38 for(i=1;i<=n;i++)id[read()]=i; 39 puts(check()?"YES":"NO"); 40 } 41 }