您的位置:首页 > 其它

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

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

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
const int MAXN=20000+50;
int n,m;
int u[MAXN],v[MAXN],pos[MAXN];
vector<int> E[MAXN];
int dfn[MAXN],low[MAXN],instack[MAXN],col[MAXN],cnt,colcnt;
stack<int> S;

int cross(int i,int j)
{
int x1=pos[u[i]],y1=pos[v[i]],x2=pos[u[j]],y2=pos[v[j]];
if ((x1<x2 && x2<y1 && y1<y2) || (x2<x1 && x1<y2 && y2<y1)) return 1;else return 0;
}

void addedge(int u,int v)
{
E[u].push_back(v);
E[v].push_back(u);
}

void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
S.push(u);
instack[u]=1;

for (int i=0;i<E[u].size();i++)
{
int son=E[u][i];
if (!instack[son])
{
tarjan(son);
low[u]=min(low[son],low[u]);
}
else
if (instack[son]==1)
low[u]=min(dfn[son],low[u]);
}

if (dfn[u]==low[u])
{
colcnt++;
int x;
do
{
x=S.top();
S.pop();
col[x]=colcnt;
instack[x]=2;
}while (x!=u);
}
}

void init()
{
scanf("%d%d",&n,&m);
cnt=0,colcnt=0;
for (int i=0;i<MAXN;i++) vector<int>().swap(E[i]);//注意不要忘记清空
memset(instack,0,sizeof(instack));
for (int i=1;i<=m;i++)
scanf("%d%d",&u[i],&v[i]);
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
pos[x]=i;
}
}

void build()
{
for (int i=1;i<=m;i++)
if (pos[u[i]]>pos[v[i]]) swap(u[i],v[i]);
for (int i=1;i<=m;i++)
for (int j=i+1;j<=m;j++)
if (cross(i,j))
{
addedge(i,j+m);
addedge(i+m,j);
}
}

void solve()
{
for (int i=1;i<=2*m;i++) if (!instack[i]) tarjan(i);
int f=1;
for (int i=1;i<=m;i++)
if (col[i]==col[i+m])
{
f=0;
break;
}
if (f) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}

int main()
{
int T;
scanf("%d",&T);
while (T--)
{
init();
if (m<=3*n-6)//平面图定理
{
build();
solve();
}
else
cout<<"NO"<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: