• bzoj1997: [Hnoi2010]Planar


    把回路的边想像成一个环,对于不在此上的边,有两种画法:在环内或环外

    这就构成了2-sat二选一的要求。YY一下,容易想到构图。

    然而状态很差写得很慢

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct node
    {
        int x,y,next;
    }a[2100000];int len,last[21000];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    int z,dfn[21000],low[21000];
    int top,sta[21000];bool v[21000];
    int cnt,bel[21000];
    void SCC(int x)
    {
        dfn[x]=low[x]=++z;
        sta[++top]=x;v[x]=true;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(dfn[y]==0)
            {
                SCC(y);
                low[x]=min(low[x],low[y]);
            }
            else if(v[y]==true)
                low[x]=min(low[x],dfn[y]);
        }
        if(low[x]==dfn[x])
        {
            int k;cnt++;
            do
            {
                k=sta[top];top--;
                v[k]=false;
                bel[k]=cnt;
            }while(k!=x);
        }
    }
    
    struct edge{int x,y;}e[21000];
    int pos[21000];
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int n,m,x;
            scanf("%d%d",&n,&m);
            
            for(int i=1;i<=m;i++)
                scanf("%d%d",&e[i].x,&e[i].y);
            for(int i=1;i<=n;i++)
                scanf("%d",&x),pos[x]=i;
            if(m>3*n-6){printf("NO
    ");continue;}
            
            int tp=0;
            for(int i=1;i<=m;i++)
            {
                e[i].x=pos[e[i].x];e[i].y=pos[e[i].y];
                if(e[i].x>e[i].y)swap(e[i].x,e[i].y);
                if(e[i].y-e[i].x==1||(e[i].y==n&&e[i].x==1))continue;
                e[++tp].x=e[i].x,e[tp].y=e[i].y;
            }
            m=tp;
            
            len=0;memset(last,0,sizeof(last));
            for(int i=1;i<=m;i++)
                for(int j=i+1;j<=m;j++)
                    if( (e[i].x<e[j].x&&e[j].x<e[i].y&&e[i].y<e[j].y) ||
                        (e[j].x<e[i].x&&e[i].x<e[j].y&&e[j].y<e[i].y))
                    {
                        ins(i,j+m);
                        ins(i+m,j);
                        ins(j,i+m);
                        ins(j+m,i);
                    }
            
            z=top=cnt=0;
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(v,false,sizeof(v));
            for(int i=1;i<=2*m;i++)
                if(dfn[i]==0)SCC(i);
            
            bool bk=true;
            for(int i=1;i<=m;i++)
                if(bel[i]==bel[i+m]){bk=false;break;}
            if(bk)printf("YES
    ");
            else  printf("NO
    ");
        }
        return 0;
    }
  • 相关阅读:
    C++ 11 Lambda表达式
    Hello word!
    nginx 官方文档翻译
    Http读书笔记1-5章
    ROM、RAM、DRAM、SRAM和FLASH的区别
    优化专题
    Typescript学习
    canvas实现的粒子效果
    【转载】js常用方法和片段
    【转载】图解正向代理、反向代理、透明代理
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9556250.html
Copyright © 2020-2023  润新知