【2-SAT(tarjan)】BZOJ1997-[Hnoi2010]Planar

【题目大意】
给出一张存在哈密顿回路的无向图,判断是否是平面图。
【思路】
首先平面图的一个性质:边数<=点数*3-6
因为存在哈密顿回路,可以将回路看作是一个圆,考量不再哈密顿回路中的边。如果两天边相交(判断相交可以随意yy一下),那么必然一条在圆内一条在圆外,显然是2-SAT。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<stack>
  7 using namespace std;
  8 const int MAXN=20000+50;
  9 int n,m;
 10 int u[MAXN],v[MAXN],pos[MAXN];
 11 vector<int> E[MAXN];
 12 int dfn[MAXN],low[MAXN],instack[MAXN],col[MAXN],cnt,colcnt;
 13 stack<int> S;
 14
 15 int cross(int i,int j)
 16 {
 17     int x1=pos[u[i]],y1=pos[v[i]],x2=pos[u[j]],y2=pos[v[j]];
 18     if ((x1<x2 && x2<y1 && y1<y2) || (x2<x1 && x1<y2 && y2<y1)) return 1;else return 0;
 19 }
 20
 21 void addedge(int u,int v)
 22 {
 23     E[u].push_back(v);
 24     E[v].push_back(u);
 25 }
 26
 27
 28 void tarjan(int u)
 29 {
 30     dfn[u]=low[u]=++cnt;
 31     S.push(u);
 32     instack[u]=1;
 33
 34     for (int i=0;i<E[u].size();i++)
 35     {
 36         int son=E[u][i];
 37         if (!instack[son])
 38         {
 39             tarjan(son);
 40             low[u]=min(low[son],low[u]);
 41         }
 42         else
 43         if (instack[son]==1)
 44             low[u]=min(dfn[son],low[u]);
 45     }
 46
 47     if (dfn[u]==low[u])
 48     {
 49         colcnt++;
 50         int x;
 51         do
 52         {
 53              x=S.top();
 54              S.pop();
 55              col[x]=colcnt;
 56              instack[x]=2;
 57         }while (x!=u);
 58     }
 59 }
 60
 61
 62 void init()
 63 {
 64     scanf("%d%d",&n,&m);
 65     cnt=0,colcnt=0;
 66     for (int i=0;i<MAXN;i++) vector<int>().swap(E[i]);//注意不要忘记清空
 67     memset(instack,0,sizeof(instack));
 68     for (int i=1;i<=m;i++)
 69         scanf("%d%d",&u[i],&v[i]);
 70     for (int i=1;i<=n;i++)
 71     {
 72         int x;
 73         scanf("%d",&x);
 74         pos[x]=i;
 75     }
 76 }
 77
 78 void build()
 79 {
 80     for (int i=1;i<=m;i++)
 81         if (pos[u[i]]>pos[v[i]]) swap(u[i],v[i]);
 82     for (int i=1;i<=m;i++)
 83         for (int j=i+1;j<=m;j++)
 84             if (cross(i,j))
 85             {
 86                 addedge(i,j+m);
 87                 addedge(i+m,j);
 88             }
 89 }
 90
 91 void solve()
 92 {
 93     for (int i=1;i<=2*m;i++) if (!instack[i]) tarjan(i);
 94     int f=1;
 95     for (int i=1;i<=m;i++)
 96         if (col[i]==col[i+m])
 97         {
 98             f=0;
 99             break;
100         }
101     if (f) cout<<"YES"<<endl;
102         else cout<<"NO"<<endl;
103 }
104
105 int main()
106 {
107     int T;
108     scanf("%d",&T);
109     while (T--)
110     {
111         init();
112         if (m<=3*n-6)//平面图定理
113         {
114             build();
115             solve();
116         }
117         else
118             cout<<"NO"<<endl;
119     }
120     return 0;
121 } 
时间: 2024-10-12 13:03:09

【2-SAT(tarjan)】BZOJ1997-[Hnoi2010]Planar的相关文章

【强连通分量&#183;Tarjan】bzoj1179: [Apio2009]Atm

新博的第一发! 因为这几天切了几道强连通分量,所以从这里begin [题目描述] Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定,在每个路口都设立了一个Siruseri 银行的ATM 取款机.令人奇怪的是,Siruseri的酒吧也都设在路口,虽然并不是每个路口都设有酒吧.Banditji 计划实施Siruseri 有史以来最惊天动地的ATM 抢劫.他将从市中心出发,沿着单向道路行驶,抢劫所有他途径的ATM 机,最终他将在一个酒吧庆祝他的胜利.使用高超的黑客技术,他获

BZOJ1997 [Hnoi2010]Planar (2-sat)

题意:给你一个哈密顿图,判断是不是平面图 思路:先找出哈密顿图来.哈密顿回路可以看成一个环,把边集划分成两个集合,一个在环内,一个在外.如果有两条相交边在环内,则一定不是平面图,所以默认两条相交边,转化成2——sat,两条边不能同时在内或外,注意双向加边.(以边来转化成两倍) 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<queue> 5 #include<

bzoj1997: [Hnoi2010]Planar

2-SAT. 首先有平面图定理 m<=3*n-6,如果不满足这条件肯定不是平面图,直接退出. 然后构成哈密顿回路的边直接忽略. 把哈密顿回路当成一个圆, 如果俩条边交叉(用心去感受),只能一条边在圆内,另一条在圆外. 这个是2-sat的A,B要不同时取,要不同时不取模型. 如果俩个交叉,只能一个在内,一个在外. 和A,B俩者不能同时取有区别,需要注意. 可能存在3个方案(A,B'),(B,A'),(A',B'). 连方案都不要,直接tarjan完就过了. #include<cstdio>

POJ1523 SPF 【求割点Tarjan】

SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6131   Accepted: 2814 Description Consider the two networks shown below. Assuming that data moves around these networks only between directly connected nodes on a peer-to-peer basis, a

【BZOJ1997】[Hnoi2010]Planar 2-SAT

[BZOJ1997][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 题解:跟HDU的某熊猫题一模一样?(然而我并没有写那题的题解~) 本题可以理解为圆上有一些点之间要连线,这些线要么在圆里要么在圆外,问能否让所有的线都不

POJ 1904:King&#39;s Quest【tarjan】

题目大意:给出一个二分图的完美匹配(王子和公主的烧死名单表),二分图x部和y部均只有n个点,问对于每一个x部的点,他能选择哪些点与之匹配 使得与之匹配后,剩余图的最大匹配仍然是n 思路:这题是大白书379页二分图的压轴题,在图论刷的题还不多时思考过这题,现在想来也不难想 这题引人瞩目的一点便是预先给出了一个二分图的初始匹配 对每个点枚举后增广显然不怎么可行,那么还是图论问题的经典思考方式,点和边各表示什么 题目的输入天然的给出了一个图,但对这题好像没什么用处,于是开始思考把给出的初始匹配的每条边

poj3207:Ikki&#39;s Story IV-Panda&#39;s Trick【2-sat tarjan】

题目大意:圆盘上顺次安放0, 1, 2, …, n – 1的点,每次给出两个点需要连边,可以选择在圆盘的正面连边或在圆盘的反面连边,问是否存在一种方案使得所有连线不相交? 思路:本问题可以等价成:圆盘上原本有N条线,每条线在正反面都有画上,将在正反面的两条线只保留一根,问是否存在一种方案使得所有连线不相交? 这样问题就成了赤果果的2-SAT问题了,注意到两条线如果都在正面会相交,那么都在反面也会相交,因此构图时应是无向图,按照2-SAT的形式构完图后,用TARJAN求缩点,由于在一个SCC中的点

【NOIP模拟题】Graph(tarjan+dfs)

似乎我搞得太复杂了? 先tarjan缩点然后dfs就行了QAQ. (我不说我被一个sb错调了半个小时....不要以为缩点后dfs就可以肆无忌惮的不加特判判vis了.. bfs的做法:减反图,然后从大到小枚举(贪心),标记即可 #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorit

【BZOJ】2002: [Hnoi2010]Bounce 弹飞绵羊(lct)

(BZOJ挂了,还没在BZOJ测,先是在wikioi测过了,,) 囧.在军训时立志要学lct!!!这是一道lct的裸题,只有access操作(10行都没有啊亲...缩行大法的话,我就不说了..)(link操作相当于水过),其实lct很简单..想想都有点小激动...... lct用splay维护的话,一下就写好了..但是我在写lct的时候,发现了一些我原来splay的老问题,我原来也知道了的,就是将null的ch给赋值了,因为在rot操作里没有特判,所以导致了null的孩子被赋值了,导致我的lct

【Oracle学习笔记】

内容主要包含: (1)三种循环及其简化 (2)游标的使用 (3)异常处理 (4)存储过程 (5)存储函数 (6)触发器 (7)其他pl/sql操作 ---------------loop循环定义变量-------------------- declare cursor c1 is select * from emp;# rec emp%rowtype;# i numeber:=1; # v_count number;begin# select count(*) into v_count from