1997: [Hnoi2010]Planar 2-SAT

来源:互联网 发布:怎样才能成为网络歌手 编辑:程序博客网 时间:2024/05/19 18:00

时隔几日再回来做这个题,开始用二分图染色A掉了。
看起来建图与那个恰恰相反,恩。
若边i和边j矛盾,那么我们要连边:
i->j’,i’->j,j->i’,j’->i。
又是一道裸的2-SAT,依旧不用输出方案QAQ。

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int u[10005],v[10005],head[2005],pos[2005],dfn[2005],low[2005],belong[2005],stack[2005];int n,m,tot,sum,cnt,top,scc,flag,Case;int next[1000005],list[1000005];bool inset[2005];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void insert(int x,int y){    next[++cnt]=head[x];    head[x]=cnt;    list[cnt]=y;}void dfs(int x){    low[x]=dfn[x]=++sum;    stack[++top]=x;    inset[x]=1;    for (int i=head[x];i;i=next[i])        if (!dfn[list[i]])        {            dfs(list[i]);            low[x]=min(low[x],low[list[i]]);        }        else if (inset[list[i]]) low[x]=min(low[x],dfn[list[i]]);    if (low[x]==dfn[x])    {        int i=-1; scc++;        while (i!=x)        {            i=stack[top--];            belong[i]=scc;            inset[i]=0;        }    }}inline void tarjan(){    for (int i=1;i<=2*tot;i++) if (!dfn[i]) dfs(i);}int main(){    Case=read();    while (Case--)    {        memset(head,0,sizeof(head));        memset(dfn,0,sizeof(dfn));        flag=tot=sum=top=cnt=scc=0;        n=read(); m=read();        for (int i=1;i<=m;i++) u[i]=read(),v[i]=read();        for (int i=1,x;i<=n;i++) x=read(),pos[x]=i;        if (m>3*n-6) {puts("NO"); continue;}        for (int i=1;i<=m;i++)        {            u[i]=pos[u[i]]; v[i]=pos[v[i]];            if (u[i]>v[i]) swap(u[i],v[i]);            if (v[i]-u[i]==1||v[i]-u[i]==n-1) continue;            u[++tot]=u[i]; v[tot]=v[i];        }        for (int i=1;i<=tot;i++)            for (int j=i+1;j<=tot;j++)                if ((u[i]<u[j]&&u[j]<v[i]&&v[i]<v[j])||(u[j]<u[i]&&u[i]<v[j]&&v[j]<v[i]))                    insert(2*i-1,2*j),insert(2*j-1,2*i),insert(2*i,2*j-1),insert(2*j,2*i-1);        tarjan();        for (int i=1;i<=tot;i++)            if (belong[2*i-1]==belong[2*i]) {flag=1; break;}        flag?puts("NO"):puts("YES");    }    return 0;}
0 0
原创粉丝点击