1997: [Hnoi2010]Planar
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1509 Solved: 585
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
Source
Day1
三种做法,并查集,二分图判定,2-SAT
前两种就是上一道题的check,但是注意要剪枝,m<=3n-6时才有可能成为平面图。
2-SAT解法:
这道题把所有边拆成两个,分别代表在里面和在外面,然后又里面和外面取且一定取一个,那么连上四条边即可。。
又因为这道题只用判断可行性,那么就只用缩点之后判断是否有冲突即可,如果要输出方案,那么就需要按照拓扑序的反序进行点的确定,然后依次标记可选的点,传递不能选的标记,然后该图的染色就是2-SAT问题的解。
另外要注意提前break的时候要保证读完该组数据,不然RE…
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
const int INF=0x3f3f3f3f;
const int maxnode = 205;
const int maxn = 605;
const int maxm = 10005;
struct Edge
{
int to,next;
}edge[maxn*maxn<<2]; // 4 edges per condition
int head[maxn<<1]; // divided
int maxedge;
inline void addedge(int u,int v)
{
edge[++maxedge] = (Edge) { v,head[u] };
head[u] = maxedge;
}
struct Road
{
int u,v;
}road[maxn],save[maxm];
bool g[maxnode][maxnode];
int a[maxnode],order[maxnode];
int n,m,tmp;
void init()
{
memset(g,0,sizeof(g));
memset(head,-1,sizeof(head));
maxedge = -1;
m=0;
for(int i=1;i<=tmp;i++) scanf("%d%d",&save[i].u,&save[i].v);
for(int i=1;i<=n;i++) scanf("%d",a+i),order[a[i]]=i;
if(tmp>n*3-6) return; // spacial judge after scanning!!
for(int i=1;i1]] = g[a[i+1]][a[i]] = true;
g[a[1]][a[n]] = g[a[n]][a[1]] = true;
for(int i=1;i<=tmp;i++) if(!g[save[i].u][save[i].v]) road[++m]=save[i];
}
inline bool cross(int i,int j) // cases of including node n,1 is considered another way
{
int x1=order[road[i].u],y1=order[road[i].v];
int x2=order[road[j].u],y2=order[road[j].v];
if(x1>y1) swap(x1,y1);
if(x2>y2) swap(x2,y2);
return (x1int dfn[maxn<<1],sccno[maxn<<1];
bool insta[maxn<<1];
int scc_cnt,dfs_clock;
stack <int> sta;
int dfs(int u)
{
int lowu=dfn[u]=++dfs_clock;
sta.push(u); insta[u]=true;
for(int i=head[u];~i;i=edge[i].next)
{
int v = edge[i].to;
if(!dfn[v])
{
int lowv = dfs(v);
smin(lowu,lowv);
}
else if(insta[v]) smin(lowu,dfn[v]);
}
if(lowu>=dfn[u])
{
scc_cnt++;
int t;
do
{
t=sta.top(); sta.pop(); insta[t]=false;
sccno[t]=scc_cnt; // if needed to print , note the nodes of SCC
}while(t^u);
}
return lowu;
}
void Tarjan()
{
memset(dfn,0,sizeof(dfn));
memset(sccno,0,sizeof(sccno));
dfs_clock = scc_cnt = 0;
for(int i=1;i<=m;i++)
{
if(!dfn[i]) dfs(i);
if(!dfn[i+m]) dfs(i+m);
}
}
inline bool check()
{
for(int i=1;i<=m;i++)
if(sccno[i] == sccno[i+m]) return false;
return true;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("planar.in","r",stdin);
freopen("planar.out","w",stdout);
#endif
int cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&tmp);
init();
if(tmp>n*3-6) // judge after scanning all data!!
{
printf("NO\n");
continue;
}
for(int i=1;ifor(int j=i+1;j<=m;j++)
if(cross(i,j))
{
addedge(i,j+m);
addedge(j,i+m);
addedge(i+m,j);
addedge(j+m,i);
}
Tarjan();
if(check()) printf("YES\n");
else printf("NO\n");
}
return 0;
}