BZOJ 1997: [Hnoi2010]Planar( 2sat )

平面图中E ≤ V*2-6..

一个圈上2个点的边可以是在外或者内, 经典的2sat问题..

------------------------------------------------------------------------------------------

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<stack>

using namespace std;

#define U(x) U[r[x]]

#define V(x) V[r[x]]

#define H(x) H[r[x]]

const int maxn = 20009;

struct edge {

int to;

edge* next;

} E[1000000], *pt, *head[maxn];

void AddEdge(int u, int v) {

pt->to = v; pt->next = head[u]; head[u] = pt++;

}

int Low[maxn], Dfn[maxn], Scc[maxn], CK, scc_n;

int U[maxn], V[maxn], H[maxn], P[maxn], _P[maxn], r[maxn], n;

int N, M, T;

stack<int> S;

void Init() {

pt = E;

memset(head, 0, sizeof head);

scanf("%d%d", &N, &M);

for(int i = 0; i < M; i++)

scanf("%d%d", U + i, V + i);

for(int i = 0; i < N; i++) {

scanf("%d", _P + i);

P[_P[i]] = i;

}

for(int i = 0; i < N; i++)

H[_P[i]] = _P[(i + 1) % N];

n = scc_n = CK = 0;

memset(Dfn, 0, sizeof Dfn);

memset(Scc, 0, sizeof Scc);

while(!S.empty()) S.pop();

}

bool chk(int l, int r, int _l, int _r) {

if(l > r) swap(l, r);

if(_l > _r) swap(_l, _r);

return (l < _l && _l < r && r < _r) || (_l < l && l < _r && _r < r);

}

void Tarjan(int x) {

Dfn[x] = Low[x] = ++CK;

S.push(x);

for(edge* e = head[x]; e; e = e->next) if(!Dfn[e->to]) {

Tarjan(e->to);

Low[x] = min(Low[x], Low[e->to]);

} else if(!Scc[e->to])

Low[x] = min(Low[x], Dfn[e->to]);

if(Dfn[x] == Low[x]) {

int t; scc_n++;

do {

t = S.top(); S.pop();

Scc[t] = scc_n;

} while(t != x);

}

}

bool Solve() {

if(M > 3 * N - 6) return false;

for(int i = 0; i < M; i++)

if(V[i] != H[U[i]] && U[i] != H[V[i]]) r[n++] = i;

for(int i = 0; i < n; i++)

for(int j = 0; j < i; j++)

if(chk(P[U(i)], P[V(i)], P[U(j)], P[V(j)])) {

AddEdge(i * 2, j * 2 + 1);

AddEdge(i * 2 + 1, j * 2);

AddEdge(j * 2, i * 2 + 1);

AddEdge(j * 2 + 1, i * 2);

}

for(int i = 0; i < 2 * n; i++) {

if(!Dfn[i]) Tarjan(i);

}

for(int i = 0; i < n; i++)

if(Scc[i * 2] == Scc[i * 2 + 1]) return false;

return true;

}

int main() {

scanf("%d", &T);

while(T--) {

Init();

puts(Solve() ? "YES" : "NO");

}

return 0;

}

------------------------------------------------------------------------------------------

1997: [Hnoi2010]Planar

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1183  Solved: 458
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

Sample Output

HINT

Source

Day1

时间: 2024-10-05 17:56:47

BZOJ 1997: [Hnoi2010]Planar( 2sat )的相关文章

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

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

BZOJ1997 [Hnoi2010]Planar (2-sat)

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

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 1997 HNOI 2010 Planar 2-SAT

题目大意:给出一个无向图,保证这个图有哈密顿回路,求这个图是不是平面图. 思路:平面图的判定条件之一:如果边数大于点数*3+6那么这个图一定不是平面图.这算是一个强剪枝吧. 我们把图中哈密顿回路的这个环上的边去掉,就变成了判定边能否不想交的2-SAT问题,POJ好像有一个原题来着.建图方法我就不说了,相信大家看到2-SAT就知道怎么写了. CODE: #include <cstdio> #include <cstring> #include <iostream> #in

【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

BZOJ 1823: [JSOI2010]满汉全席( 2-sat )

2-sat...假如一个评委喜好的2样中..其中一样没做, 那另一样就一定要做, 这样去建图..然后跑tarjan. 时间复杂度O((n+m)*K) ---------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using na