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

bzoj千题计划231:bzoj1997: [Hnoi2010]Planar_时间复杂度

Input

bzoj千题计划231:bzoj1997: [Hnoi2010]Planar_git_02

Output

bzoj千题计划231:bzoj1997: [Hnoi2010]Planar_时间复杂度_03

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
作者:xxy