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 add(int u,int v)
{
    g[u].pb(v);
}

int dfn[N],low[N],color[N],id,num,visit[N];
stack<int> S;

void DFS(int u)
{
    dfn[u]=low[u]=++id;
    S.push(u);

    int i,v;
    FOR0(i,SZ(g[u]))
    {
        v=g[u][i];
        if(!dfn[v])
        {
            DFS(v);
            upMin(low[u],low[v]);
        }
        else if(!visit[v])
        {
            upMin(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        num++;
        do
        {
            v=S.top();
            S.pop();
            visit[v]=1;
            color[v]=num;
        }while(v!=u);
    }
} 

int ok()
{
    int i;
    FOR1(i,m) if(color[i]==color[i+m]) return 0;
    return 1;
}

int cross(int x1,int y1,int x2,int y2)
{
     if(x1==x2||x1==y2||y1==x2||y1==y2) return 0;
     x1=d[x1],y1=d[y1];
     x2=d[x2],y2=d[y2];
     if(x1>y1) swap(x1,y1);
     return (x1<x2&&x2<y1)!=(x1<y2&&y2<y1);
}

int main()
{
    rush()
    {
        RD(n,m);
        int i,j,x;
        FOR1(i,m) RD(a[i],b[i]),f[i]=1;
        FOR1(i,n) RD(c[i]),d[c[i]]=i;
        if(m>3*n-6)
        {
            puts("NO");
            continue;
        }
        FOR1(i,m)
        {
            x=abs(d[a[i]]-d[b[i]]);
            if(x==1||x==n-1) f[i]=0;
        }
        int k=0;
        FOR1(i,m) if(f[i]) a[++k]=a[i],b[k]=b[i];
        m=k;
        FOR0(i,2000) g[i].clear();
        FOR1(i,m) for(j=i+1;j<=m;j++)
        {
            if(cross(a[i],b[i],a[j],b[j]))
            {
                add(i,j+m);
                add(j,i+m);
                add(i+m,j);
                add(j+m,i);
            }
        }
        clr(visit,0); clr(dfn,0); id=num=0;
        FOR1(i,m+m) if(!visit[i]) DFS(i);
        if(ok()) puts("YES");
        else puts("NO");
    }
}

BZOJ 1997 Planar(2-SAT),布布扣,bubuko.com

时间: 2025-01-05 01:31:47

BZOJ 1997 Planar(2-SAT)的相关文章

BZOJ 2561 最小生成树(最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2561 题意:给定一个边带正权的连通无向图G= (V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树 上? 思路:考虑克鲁斯卡尔算法的过程.若加入的 边(u,v,L)能够出现在最小生成树中,那么权值小于L的边

BZOJ 2661 连连看(费用流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2661 题意:给出一个区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x^2-y^2是一个完全平方数z^2,并且y与z互质,那么就可以将x和y一起消除,同时得到x+y点分数.要求就是,消除的数对尽可能多的前提下,得到的分数尽量多. 思路:首先暴力出所有合法的数对(x,y).然后将每个用到的数字拆成两个点,每个数对连一条边.最后的答案除以2即可. struct nod

BZOJ 1912 巡逻(树直径)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1912 题意:给出一棵树,边权为1.现在加一条或两条边后,使得从1出发遍历每个点至少一次再回到1的路程最短. 思路:先求一次树的直径Max1.然后将直径的边权改为-1,再求一次直径Max2.答案为ans=(n-1)*2-(Max1-1)-(Max2-1). struct node { int u,v,w,next; }; node edges[N<<1]; int head[N],e;

BZOJ 2331 地板(插头DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2331 题意:给出一个n*m的地面.有些是障碍.用L型的地板砖铺满.有多少种方案. 思路:用0表示没有插头,用1表示有插头且可以拐弯,用3表示有插头但是不能再拐弯了. 设有m列,轮廓线为[0,m].对于格子(i,j),设左插头x上插头y,那么转移有: (1)x=0,y=0:此时如图1-0,有三种转移,分别是1-1,1-2,1-3; (2)x!=0,y!=0:此时只有当x=y=1时可以转移

(2 sat) hdu 1824

Let's go home Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1523    Accepted Submission(s): 616 Problem Description 小时候,乡愁是一枚小小的邮票,我在这头,母亲在那头.                        —— 余光中 集训是辛苦的,道路是坎坷的,休息还是

[BZOJ 4318]OSU!(期望dp)

Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: 一共有n次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,n次操作对应为1个长度为n的01串.在这个串中连续的 X个1可以贡献X^3 的分数,这x个1不能被其他连续的1所包含(也就是极长的一串1,具体见样例解释) 现在给出n,以及每个操作的成功率,请你输出期望分数,输出四舍五入后保留1位小数. Solution 和上一题差不多…双倍经验~ 平方的期望并不等于期望的平方,所以还

LA 3211 飞机调度(2—SAT)

https://vjudge.net/problem/UVALive-3211 题意: 有n架飞机需要着陆,每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种,第i架飞机的早着陆时间为E,晚着陆时间为L,不得在其他时间着陆.你的任务是为这些飞机安排着陆方式,使得整个着陆计划尽量安全.换句话说,如果把所有飞机的实际着陆时间按照从早到晚的顺序排列,相邻两个着陆时间间隔的最小值. 思路: 二分查找最大值P,每次都用2—SAT判断是否可行. 1 #include<iostream>

bzoj 1176 Mokia(CDQ分治)

[题目链接]  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=96974 [题意] 定义查询操作与修改操作:1 x y z 为将格子(x,y)修改为z:2 x1 y1 x2 y2为查询以(x1,y1)为左上(x2,y2)为右下的子矩阵之和. [思路] cdq分治. 矩阵初始值都为s,所以先不考虑. 首先明确每一个修改操作都互不影响.然后把每一个对子矩阵的询问操作差分为对四个点的“前缀和”操作. 先把所有的操作按照x升序排列

BZOJ 2157 旅游(动态树)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2157 [题目大意] 支持修改边,链上查询最大值最小值总和,以及链上求相反数 [题解] 我们将边转化成点,直接用LCT可以处理以上操作 [代码] #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=200010; int n; co