bzoj1997[Hnoi2010]Planar 2-SAT

来源:互联网 发布:网络分布式继电器接线 编辑:程序博客网 时间:2024/05/19 17:03

跟poj3207的思想差不多,就是圆上的两条边如果相交,一定得有一条在圆外,然后就是2-SAT的模型了。
要注意一下直接上2-SAT会爆炸,加一个剪枝,就是平面图要求边数<=3n-6
好像还可以用并查集做。

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=1e5+5;const int inf=1e9;int n,m,ind,top,cnt,scc;int x[N],y[N];int c[N],pos[N];int head[N],next[N*10],go[N*10],dfn[N],low[N],bl[N],q[N];bool vis[N];int tot;inline void add(int x,int y){    go[++tot]=y;    next[tot]=head[x];    head[x]=tot;} inline void tarjan(int x){    vis[x]=1,q[++top]=x;    low[x]=dfn[x]=++ind;    for(int i=head[x];i;i=next[i])    {        int v=go[i];        if (!dfn[v])tarjan(v),low[x]=min(low[x],low[v]);        else if (vis[v])low[x]=min(low[x],dfn[v]);    }    if (low[x]==dfn[x])    {        scc++;        int t=-1;        while (t!=x)        {            t=q[top--];            vis[t]=0;            bl[t]=scc;        }    }}inline bool pd(){    fo(i,1,m)    if (bl[2*i]==bl[2*i-1])return 0;    return 1;}int main(){    int cas;    scanf("%d",&cas);    while (cas--)    {        scanf("%d%d",&n,&m);        fo(i,1,m)scanf("%d%d",&x[i],&y[i]);        tot=0,memset(head,0,sizeof(head));        scc=ind=0;        memset(low,0,sizeof(low));        memset(dfn,0,sizeof(dfn));        fo(i,1,n)scanf("%d",&c[i]),pos[c[i]]=i;        if (m>3*n-6)        {            puts("NO");            continue;        }        top=0;        fo(i,1,m)        {            y[i]=pos[y[i]],x[i]=pos[x[i]];            if (x[i]>y[i])swap(x[i],y[i]);            if (y[i]-x[i]==1||(y[i]==n&&x[i]==1))continue;            x[++top]=x[i],y[top]=y[i];        }        m=top;        fo(i,1,m)        fo(j,i+1,m)        if ((x[i]<x[j]&&x[j]<y[i]&&y[i]<y[j])||(x[j]<x[i]&&x[i]<y[j]&&y[j]<y[i]))        {            add(2*i-1,2*j);            add(2*i,2*j-1);            add(2*j-1,2*i);            add(2*j,2*i-1);        }        top=0;        fo(i,1,2*m)if (!dfn[i])tarjan(i);        if (pd())puts("YES");        else printf("NO\n");    }}
原创粉丝点击