zoukankan      html  css  js  c++  java
  • bzoj千题计划231:bzoj1997: [Hnoi2010]Planar

    http://www.lydsy.com/JudgeOnline/problem.php?id=1997

    如果两条边在环内相交,那么一定也在环外相交

    所以环内相交的两条边,必须一条在环内,一条在环外

    这就成了2-sat问题

    时间复杂度为(T*(m^2+n)),T 飞

    平面图有一个结论:边数<=点数*3-6

    m就与n同阶了

    判断两条边是否在环内相交:

    设一条边为(ui,vi),一条半为(uj,vj)

    且 u在环上的编号<v

    如果 ui<uj<vi<vj,则两条边会在环内相交

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 1205
    #define M 1440001
    
    int n,m;
    
    struct node
    {
        int u,v;
    }e[10001],g[10001];
    
    int pos[N];
    
    int tot,front[N],to[M],nxt[M];
    
    int low[N],dfn[N];
    int st[N],top;
    
    int id[N],cnt;
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    bool init()
    {
        read(n); read(m);
        for(int i=1;i<=m;++i) read(e[i].u),read(e[i].v);
        int x;
        for(int i=1;i<=n;++i)
        {
            read(x);
            pos[x]=i;
        }
        return m<=3*n-6;
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
    }
    
    void build()
    {
        int mm=0;
        int u,v;
        for(int i=1;i<=m;++i)
        {
            u=e[i].u; v=e[i].v;
            if(pos[u]>pos[v]) swap(u,v);
            if(pos[v]==pos[u]+1) continue;
            if(pos[v]==n && pos[u]==1) continue;
            g[++mm].u=u; g[mm].v=v;
        }
        m=mm;
        for(int i=1;i<=m;++i)
            for(int j=1;j<=m;++j)
                if(i!=j)    
                    if(pos[g[i].u]<pos[g[j].u] && pos[g[j].u]<pos[g[i].v] && pos[g[i].v]<pos[g[j].v])
                        add(i<<1,j<<1|1),add(j<<1,i<<1|1);
    }
    
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tot;
        st[++top]=x;
        for(int i=front[x];i;i=nxt[i])
            if(!dfn[to[i]]) 
            {
                tarjan(to[i]);
                low[x]=min(low[x],low[to[i]]);
            }
            else low[x]=min(low[x],dfn[to[i]]);
        if(low[x]==dfn[x])
        {
            cnt++;
            while(st[top]!=x) id[st[top--]]=cnt;
            id[x]=cnt;
            top--;
        }
    }
        
    void solve()
    {
        tot=0;
        for(int i=1;i<=m;++i)
        {
            if(!dfn[i<<1]) tarjan(i<<1);
            if(!dfn[i<<1|1]) tarjan(i<<1|1);
        }
        for(int i=1;i<=m;++i)
            if(id[i<<1]==id[i<<1|1]) 
            {
                puts("NO");
                return;
            }
        puts("YES");
    }
    
    void clear()
    {
        tot=cnt=0;
        memset(front,0,sizeof(front));
        memset(dfn,0,sizeof(dfn));
    }
    
    int main()
    {
        int T;
        read(T);
        while(T--)
        {
            if(!init()) 
            {
                puts("NO");
                continue;
            }
            clear();
            build();
            solve();
        }
    }            

    1997: [Hnoi2010]Planar

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 2445  Solved: 916
    [Submit][Status][Discuss]

    Description

    Input

    Output

    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
  • 相关阅读:
    macOS 系统下载地址
    docker基本使用-nginx
    adb命令安装apk
    docker基本使用-常用命令
    docker基本使用-安装
    Vue技术点整理-vue.config.js
    flutter环境部署
    Android webview 问题记录
    Node 使用webpack编写简单的前端应用
    前端api管理工具YApi
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8439041.html
Copyright © 2011-2022 走看看