边不一定在环内!
Solution [HNOI2010]平面图判定
题目大意:给定一个存在哈密顿回路的图,判定它是不是平面图
2-SAT
分析:
首先有一个性质:对于极大平面图,有(m = 3n - 6)
萌新yy的证明:考虑归纳法
对于(n=3)时,(m=3),成立
因为是极大平面图,所以我们每新加入一个点希望增加的边尽量多,我们贪心的加入三角形中,每加入一个点增加(3)条边,证毕
所以对于(m > 3n-6)一定不存在平面图,所以(m leq 594)
然后对于一条边,我们可以把它放在环内也可以把它放在环外,我们(m^2)暴力枚举每一对边,如果两边同时放在环内相交,它们就不能同时存在于环内(或环外),2-SAT即可
对点重新标号貌似会比较简单的样子……
#include <algorithm>
#include <cstdio>
#include <cctype>
#include <vector>
#include <stack>
using namespace std;
inline int read(){
int x = 0;char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))x = x * 10 + c - '0',c = getchar();
return x;
}
namespace graph{
const int maxn = 3e4;
vector<int> G[maxn];
inline void addedge(int from,int to){G[from].push_back(to);}
int dfn[maxn],low[maxn],col[maxn],instk[maxn],col_tot,dfs_tot;
stack<int> stk;
inline void tarjan(int u){
dfn[u] = low[u] = ++dfs_tot;
stk.push(u),instk[u] = 1;
for(int v : G[u])
if(!dfn[v])tarjan(v),low[u] = min(low[u],low[v]);
else if(instk[v])low[u] = min(low[u],dfn[v]);
if(low[u] == dfn[u]){
int t;
col_tot++;
do{
t = stk.top();stk.pop(),instk[t] = 0;
col[t] = col_tot;
}while(t != u);
}
}
}
struct Edge{int from,to;}Edges[16384];
int n,m,t,to[256];
inline int qaq(int a,int b,int x){return a < x && x < b;}
inline int qwq(int a,int b,int x){return x < a || x > b;}
inline void solve(){
graph::col_tot = graph::dfs_tot = 0;
for(int i = 1;i <= 2 * m;i++)graph::dfn[i] = graph::low[i] = graph::col[i] = graph::instk[i] = 0,graph::G[i].clear();
n = read(),m = read();
for(int i = 1;i <= m;i++)Edges[i].from = read(),Edges[i].to = read();
for(int i = 1;i <= n;i++)to[read()] = i;
if(m > 3 * n - 6){
puts("NO");
return;
}
for(int i = 1;i <= m;i++){
Edge &e = Edges[i];
e.from = to[e.from];
e.to = to[e.to];
if(e.from > e.to)swap(e.from,e.to);
}
for(int i = 1;i <= m;i++)
for(int j = 1;j < i;j++){
const Edge &a = Edges[i],&b = Edges[j];
if((qaq(a.from,a.to,b.from) && qwq(a.from,a.to,b.to)) || (qaq(a.from,a.to,b.to) && qwq(a.from,a.to,b.from))){
graph::addedge(i,j + m);
graph::addedge(j + m,i);
graph::addedge(i + m,j);
graph::addedge(j,i + m);
}
}
for(int i = 1;i <= 2 * m;i++)
if(!graph::dfn[i])graph::tarjan(i);
for(int i = 1;i <= m;i++)
if(graph::col[i] == graph::col[i + m]){
puts("NO");
return;
}
puts("YES");
}
int main(){
t = read();
while(t--)solve();
return 0;
}