BZOJ 1997: [Hnoi2010]Planar 2-SAT+並查集
title
描述 Description
若能將無向圖 G=(V,E)畫在平面上使得任意兩條無重合頂點的邊不相交,則稱 G 是平面圖。 判定一個圖是否為平面圖的問題是圖論中的一個重要問題。現在假設你要判定的是一類特殊的 圖,圖中存在一個包含所有頂點的環,即存在哈密頓迴路。
輸入格式 Input Format
輸入檔案第一行是一個正整數T,表示資料組數(每組資料描述一個要判定的圖)。接下來從輸入檔案第二行開始有T組資料,每組資料的第一行是用空格隔開的兩個正整數N和M,分別表示對應圖的頂點數和邊數。緊接著的M行,每行是用空格隔開的 兩個正整數u和v(1≤u,v≤N),表示對應圖的一條邊(u,v),輸入的資料保證所有邊僅出現一次。
每組資料的最後一行是用空格隔開的N個正整數,從左到右表示對應圖中的一個哈密頓迴路:V1, V2, ?, VN,即對任意i≠j有Vi≠Vj且對任意1≤i≤N-1有(Vi,Vi+1)∈E及(V1,VN)∈E。
輸出格式 Output Format
輸出包含 T 行,若輸入檔案的第 i 組資料所對應圖是平面圖,則在第 i 行 輸出 YES,否則在第 i 行輸出 NO,注意均為大寫字母。
樣例輸入 Sample Input
2
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
5 5
1 2
2 3
3 4
4 5
5 1
1 2 3 4 5
樣例輸出 Sample Output
NO
YES
時間限制 Time Limitation
1s
註釋 Hint
輸入的資料
保證100%的資料滿足T≤100,3≤N≤200,M≤10000
來源 Source
hnoi2010
code
#include<bits/stdc++.h>
using namespace std;
const int maxn=410;
const int maxm=1e5+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxm<<2],Next[maxm<<2],head[maxm<<1],len;
inline void add(int x,int y)
{
ver[++len]=y,Next[len]=head[x],head[x]=len;
}
int pos[maxm],Ex[maxm],Ey[maxm],n,m;
inline int cross(int a,int b)
{
register int fi1=pos[Ex[a]],fi2=pos[Ex[b]];
register int se1=pos[Ey[a]],se2=pos[Ey[b]];
if (fi1>se1) swap(fi1,se1);
if (fi2>se2) swap(fi2,se2);
if (fi1<fi2 && se1<se2 && fi2<se1) return 1;
if (fi1>fi2 && se1>se2 && fi1<se2) return 1;
return 0;
}
int dfn[maxm<<1],low[maxm<<1],id;
int Stack[maxm<<1],top;
int belong[maxm<<1],tot;
bool instack[maxm<<1];
inline void tarjan(int x)
{
dfn[x]=low[x]=++id;
Stack[++top]=x;
instack[x]=1;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if (!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if (instack[y])
low[x]=min(low[x],dfn[y]);
}
if (low[x]==dfn[x])
{
int k;
++tot;
do
{
k=Stack[top--];
instack[k]=0;
belong[k]=tot;
} while (k!=x);
}
}
int u[maxm],v[maxm],num;
int a[maxn][maxn];
inline bool check()
{
for (register int i=1;i<=num;++i)
if (belong[i]==belong[i+m])
return 0;
return 1;
}
inline void Clear()
{
id=len=tot=top=num=0;
memset(a,0,sizeof(a));
memset(pos,0,sizeof(pos));
memset(instack,0,sizeof(instack));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(belong,0,sizeof(belong));
memset(head,0,sizeof(head));
}
int main()
{
int t;
read(t);
while (t--)
{
Clear();
read(n);read(m);
for (int i=1;i<=m;++i)
read(u[i]),read(v[i]);
int first;read(first);
int x=first;
pos[x]=1;
for (int i=2,y;i<=n;++i)
read(y),pos[y]=i,a[x][y]=a[y][x]=1,x=y;
a[x][first]=a[first][x]=1;
if (m>n*3-6)
{
puts("NO");
continue;
}
for (int i=1;i<=m;++i)
if (!a[u[i]][v[i]])
Ex[++num]=u[i],Ey[num]=v[i];
for (int i=1;i<=num;++i)
for (int j=i+1;j<=num;++j)
if (cross(i,j))
add(i,j+m),add(j+m,i),
add(j,i+m),add(i+m,j);
for (int i=1;i<=num+m;++i)
if (!dfn[i]) tarjan(i);
check()?puts("YES"):puts("NO");
}
return 0;
}
相關文章
- bzoj2079: [Poi2010]Guilds(並查集)GUI並查集
- bzoj4690: Never Wait for Weights(帶權並查集)AI並查集
- BZOJ 4195 程式自動分析【並查集+離散化】並查集
- bzoj3296: [USACO2011 Open] Learning Languages(並查集)並查集
- bzoj1529: [POI2005]ska Piggy banks(並查集)並查集
- BZOJ 3673 可持久化並查集 by zky 可持續化線段樹+並查集啟發式合併持久化並查集
- bzoj2733: [HNOI2012]永無鄉(並查集+主席樹)並查集
- bzoj3444: 最後的晚餐(並查集+組合數學)並查集
- 並查集到帶權並查集並查集
- 查並集
- bzoj4195: [Noi2015]程式自動分析(離散化+並查集)並查集
- 【並查集】【帶偏移的並查集】食物鏈並查集
- 並查集(一)並查集的幾種實現並查集
- 並查集(小白)並查集
- [leetcode] 並查集(Ⅱ)LeetCode並查集
- [leetcode] 並查集(Ⅲ)LeetCode並查集
- [leetcode] 並查集(Ⅰ)LeetCode並查集
- 3.1並查集並查集
- 並查集應用並查集
- 寫模板, 並查集。並查集
- 並查集的使用並查集
- 並查集跳躍並查集
- 各種並查集並查集
- 淺談並查集並查集
- 食物鏈(並查集)並查集
- 並查集(Union Find)並查集
- The Door Problem 並查集並查集
- 並查集練習並查集
- 並查集(二)並查集的演算法應用案例上並查集演算法
- 並查集題目合集並查集
- 並查集深度應用並查集
- 並查集java實現並查集Java
- 【轉】種類並查集並查集
- The Suspects-並查集(4)並查集
- 並查集擴充套件並查集套件
- (Day3)並查集並查集
- 並查集演算法並查集演算法
- 並查集-Java實現並查集Java