BZOJ 1997: [Hnoi2010]Planar 2-SAT+並查集

~hsm~發表於2019-03-09

title

BZOJ 1997
LUOGU 3209

描述 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;
}

相關文章