Problem
題意:給定一張完全圖和圖中的一條哈密頓迴路,問是否爲平面圖
Solution
看到這題中有一條哈密頓迴路,如果這個圖是平面圖,那麼這條哈密頓迴路在平面上就是一個切割平面的圈
明顯想到每一條非哈密頓迴路上的邊不會和這個圈相交,則一定在這個圈的外部或內部
發現如果將兩條邊放在圈的同一側必定相交,那麼就必須把它倆分開(一條在裏面一條在外面),那麼對每兩條邊來說有可能有上述限制條件,最後看所有條件是否會衝突
判斷衝突的方法比較多,一般根據衝突建圖,然後tarjan、變種匈牙利、並查集隨便搞,不建圖也能用搜索水過
發現這樣的話,枚舉每兩條邊考慮限制條件是 的,然而 使得我們不得不優化這個複雜度
數學知識:一個有 個點的平面圖上最多有 條邊(在數學組小藍皮上有很多比較有用的平面圖知識)
據此可以將邊數大於 的情況預判掉,剩下的情況中邊數與點數是同一個量級 的
蒟蒻用的是並查集
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rg register
#define cl(x) memset(x,0,sizeof(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>0?(x):(-(x)))
template <typename _Tp> inline _Tp read(_Tp&x){
rg char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=205,M=10500;
int dad[M],d[M],l[M],r[M],cannot[M];
int n,m;
inline int father(int x){return dad[x]?dad[x]=father(dad[x]):x;}
int main(){
int T;read(T);while(T--){
read(n);read(m);
if(3*n+6<m){
for(rg int i=1,x;i<=m;++i)read(x),read(x);
for(rg int i=1,x;i<=n;++i)read(x);
puts("NO");continue;
}cl(dad);cl(cannot);
for(rg int i=1;i<=m;++i)read(l[i]),read(r[i]);
for(rg int i=1,x;i<=n;++i)d[read(x)]=i;
for(rg int i=1;i<=m;++i){
l[i]=d[l[i]],r[i]=d[r[i]];
if(l[i]>r[i])swap(l[i],r[i]);
if(l[i]+1==r[i]||(l[i]==1&&r[i]==n))cannot[i]=1;
}
int p1,p2;
for(rg int i=1;i<=m;++i)if(!cannot[i])
for(rg int j=i+1;j<=m;++j)if(!cannot[j])
if( (l[i]<l[j] && l[j]<r[i] && r[i]<r[j]) || (l[j]<l[i] && l[i]<r[j] && r[j]<r[i]) )
if( l[i]!=l[j] && r[i]!=r[j] && l[i]!=r[j] && r[i]!=l[j] ){
if(father(i)==father(j))goto end;
if((p1=father(i))!=(p2=father(j+m))) dad[p1]=p2;
if((p1=father(j))!=(p2=father(i+m))) dad[p1]=p2;
}
for(rg int i=1;i<=m;++i)if(father(i)==father(i+m))goto end;
puts("YES");continue;
end : puts("NO");
}
}