BZOJ 1997 HNOI 2010 Planar 2-SAT

题目大意:给出一个无向图,保证这个图有哈密顿回路,求这个图是不是平面图。

思路:平面图的判定条件之一:如果边数大于点数*3+6那么这个图一定不是平面图。这算是一个强剪枝吧。

我们把图中哈密顿回路的这个环上的边去掉,就变成了判定边能否不想交的2-SAT问题,POJ好像有一个原题来着。建图方法我就不说了,相信大家看到2-SAT就知道怎么写了。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 10010
using namespace std;

struct Edge{
    int x,y;

    Edge(int _,int __):x(_),y(__) {}
    Edge() {}
    void Read() {
        scanf("%d%d",&x,&y);
    }
}edge[MAX],stack[MAX];
int top;

int cases,points,edges;
int C[MAX];

inline bool Judge(const Edge &a,const Edge &b)
{
    return b.x > a.x && b.x < a.y && b.y > a.y;
}

namespace II_SAT{
    int head[MAX],total;
    int next[819200],aim[819200];

    int dfn[MAX],low[MAX],_clock;
    int stack[MAX],top;
    bool in_stack[MAX];
    int changed[MAX],scc;

    void Initialize() {
        total = _clock = scc = top = 0;
        memset(head,0,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(in_stack,false,sizeof(in_stack));
    }
    void Add(int x,int y) {
        next[++total] = head[x];
        aim[total] = y;
        head[x] = total;
    }
    void Tarjan(int x) {
        dfn[x] = low[x] = ++_clock;
        stack[++top] = x;
        in_stack[x] = true;
        for(int i = head[x]; i; i = next[i]) {
            if(!dfn[aim[i]])
                Tarjan(aim[i]),low[x] = min(low[x],low[aim[i]]);
            else if(in_stack[aim[i]])
                low[x] = min(low[x],dfn[aim[i]]);
        }
        if(dfn[x] == low[x]) {
            ++scc;
            int temp;
            do {
                temp = stack[top--];
                in_stack[temp] = false;
                changed[temp] = scc;
            }while(temp != x);
        }
    }
}

int main()
{
    for(cin >> cases; cases--;) {
        scanf("%d%d",&points,&edges);
        for(int i = 1; i <= edges; ++i)
            edge[i].Read();
        for(int x,i = 1; i <= points; ++i) {
            scanf("%d",&x);
            C[x] = i;
        }
        if(edges > 3 * points + 6) {
            puts("NO");
            continue;
        }
        top = 0;
        for(int i = 1; i <= edges; ++i) {
            int s = C[edge[i].x],t = C[edge[i].y];
            if(s > t)    swap(s,t);
            if(!((s + 1 == t) || (s == 1 && t == points)))
                stack[++top] = Edge(s,t);
        }
        II_SAT::Initialize();
        for(int i = 1; i <= top; ++i)
            for(int j = i + 1; j <= top; ++j)
                if(Judge(stack[i],stack[j]) || Judge(stack[j],stack[i])) {
                    II_SAT::Add(i << 1,j << 1|1);
                    II_SAT::Add(j << 1|1,i << 1);
                    II_SAT::Add(j << 1,i << 1|1);
                    II_SAT::Add(i << 1|1,j << 1);
                }
        for(int i = 2; i <= (top << 1|1); ++i)
            if(!II_SAT::dfn[i])
                II_SAT::Tarjan(i);
        bool flag = true;
        for(int i = 1; i <= top; ++i)
            if(II_SAT::changed[i << 1] == II_SAT::changed[i << 1|1]) {
                flag = false;
                break;
            }
        puts(&"NO\0YES"[flag * 3]);
    }
    return 0;
}

时间: 2024-10-17 06:22:41

BZOJ 1997 HNOI 2010 Planar 2-SAT的相关文章

【BZOJ 1997】[Hnoi2010]Planar

Description Input Output 找到哈密尔顿环之后找到不在哈密尔顿环上的边 这些边如果同时在里面相交那他们同时在外面也相交,所以只能一外一内,这就变成了2-SAT,判一下就好了 平面图性质 边数<=3*n-6 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 int T,n,m,timer,top,cnt,scc; 6 int

[HNOI 2010]Planar

Description 题库链接 给出 \(T\) 个 \(N\) 个节点 \(M\) 条边的无向图(无重边自环),并给出它们各自的哈密顿回路.分别判断每个图是否是平面图. \(T\leq 100,3\leq N\leq 200,M\leq 10000\) Solution 考虑一个带哈密顿回路的无向图,如果它是一个平面图,即可以画在平面上使得没有 \(2\) 条边需要交叉,那么哈密顿圈之外的边要么画在圈内,要么画在圈外. (绿色的环是哈密顿圈) 如果两条边 \(e,f\) ,把它们都画在圈的内

BZOJ 1997 Planar(2-SAT)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1997 题意:给出一个无向图.已知该图存在一个包含n个顶点的哈密顿回路.判定该图是不是平面图. 思路:圈将面分成内外两部分,则两条边同时在内部相交则同时在外部也是相交的.因此,必然是一个在内部一个在外部.据此建立2-SAT.平面图的边数小于等于三倍点数减六 int a[N],b[N],n,m,c[N]; int d[N],f[N]; vector<int> g[2000]; void

HDU 3062 &amp;&amp; HDU 1824 &amp;&amp; POJ 3578 &amp;&amp; BZOJ 1997 2-SAT

一条边<u,v>表示u选那么v一定被选. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 const int Maxm=21000; 7 const int Maxn=2010; 8 struct EDGE{int to,next;}edge[Maxm]; 9 int T,m

[bzoj 1911][Apio 2010]特别行动队(斜率优化DP)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 分析: 首先可以的到裸的方程f[i]=max{f[j]+a*(Si-Sj)^2+b*(Si-Sj)+c} 0<j<i 简化一下方程,我们知道对于一次项,最后结果肯定是b*Sn 所以可以写成f[i]=max{f[j]+a*(Si-Sj)^2+c} 0<j<i 我们不妨设0<x<y<i,且x比y优 即f[x]+a*(Si-Sx)^2+c>f[y]+a*

BZOJ 1997: [Hnoi2010]Planar( 2sat )

平面图中E ≤ V*2-6.. 一个圈上2个点的边可以是在外或者内, 经典的2sat问题.. ------------------------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; #

[BZOJ 1997][HNOI2010]Planar(2-SAT)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1997 分析: 考虑每条边是在圈子里面还是圈子外面 所以就变成了2-SAT判定问题了= =,于是求SCC,如果一个点对应的2个bool点在一个SCC中就无解了. 当然这样建图好像要TLE…… 然后就要上大杀器了:平面图|E|<=3|V|-6 所以,如果m>3n-6就直接输出NO了

bzoj 1997: [Hnoi2010]Planar

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 HINT Source Day1 考虑题目中给了一个哈密顿回路,那么我们把这个哈密顿回路在草稿纸上画成一个环... 然后考虑还不在环上的边,这些边有两种加入的方法,一是画在环的里面,二是画在环的外面...

BZOJ 1221 HNOI 2001 软件开发/网络流24题 餐巾计划问题 最小费用最大流

题目大意:有一个软件公司,每天需要给一些员工准备消毒毛巾,这些毛巾可以循环利用,但是需要消毒.可以将毛巾送去消毒,有两种方式,A天fA花费,B天fB花费.或者还可以直接买新毛巾,问为了满足员工的需求,至少需要花多少钱. 思路:经典的费用流问题.将每一天拆点,S向每一天<<1连边,约束每一天需要多少毛巾:每一天<<1|1向T连边,约束每一天需要的毛巾.每一天<<1向这一天清洗的毛巾能够使用的那一天<<1|1,注意A和B.毛巾可以延后使用,那么每一天<&l