hnoi2010 平面图判定 2_SAT
来源:互联网 发布:加好友的软件 编辑:程序博客网 时间:2024/06/11 13:38
【问题描述】
若能将无向图 G=(V,E)画在平面上使得任意两条无重合顶点的边不相交,则称 G 是平面图。
判定一个图是否为平面图的问题是图论中的一个重要问题。现在假设你要判定的是一类特殊的图,图中存在一个包含所有顶点的环,即存在哈密顿回路。
【输入格式】
第一行是一个正整数T,表示数据组数(每组数据描述一个要判定的图)。 接下来从输入文件第二行开始有T组数据, 每组数据的第一行是用空格隔开的两个正整数N和M,分别表示对应图的顶点数和边数。 紧接着的M行,每行是用空格隔开的两个正整数u和v(1<=u,v<=N),表示对应图的一条边(u,v),输入的数据保证所有边仅出现一次。
每组数据的最后一行是用空格隔开的N个正整数, 从左到右表示对应图中的一个哈密顿回路: V1,V2,…,VN,即对任意i≠j有Vi!=Vj且对任意1<=i<=N-1有(Vi,Vi+1)∈E及(V1,VN)∈E。
【输出格式】
包含 T 行,若输入文件的第 i 组数据所对应图是平面图, 则在第 i 行输出 YES,否则在第 i 行输出 NO,注意均为大写字母。
【输入样例】
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
【输出样例】
NO
YES
【数据范围】
保证100%的数据满足T≤100,3≤N≤200,M≤10000
————————————————————————————————————————————————————————
区分这是水题还是难题的唯一一个地方就是。。。。。
你有没有发现实际上这个边是可以绕到外面去的ORZ
开始脑补了一个并查集的算法发现有反例就上2_ SAT了,一条边只能在里面或者外面,然后和它可能有交点的边都是不能和它在同一侧的,所以就可以用2_SAT来判定了。把边当成点,然后拆成2个表示在里面和在外面。
可以发现一件事情,如果边只能走里面的话这个时候最极限的情况就是三角形剖分,这个时候一共有N*2-3条边。边走外面同理,就是把里面的翻过来而已。所以说在M>N *3-6的时候就可以直接判定为无解。
建图转化为线段相交问题,两个线段互相包含不会有交点,相交不包含才会有交点。
所以说总时间复杂度为O(T*N^3)。
AC代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<map>#include<vector>#include<cctype>using namespace std;const int maxn=205;const int maxm=10005;int T,N,M,A[maxn],id[maxn];struct edges{ int from,to; }_E[maxm];struct edge{ int to,next; }E[maxn*maxn*18];int first[maxm<<1],np,other[maxm<<1],stk[maxm<<1],top;bool vis[maxm<<1];void _scanf(int &x){ x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();}void add_edge(int u,int v){ E[++np]=(edge){v,first[u]}; first[u]=np;}void data_in(){ memset(first,0,sizeof(first)); np=0; _scanf(N);_scanf(M); int x,y; for(int i=1;i<=M;i++) { _scanf(x);_scanf(y); _E[i]=(edges){x,y}; other[i]=i+M,other[i+M]=i; } for(int i=1;i<=N;i++) _scanf(A[i]),id[A[i]]=i; if(M>N*3-6) return; for(int i=1;i<M;i++) for(int j=i+1;j<=M;j++) { int a=id[_E[i].from],b=id[_E[i].to]; int c=id[_E[j].from],d=id[_E[j].to]; if(a>b) swap(a,b); if(c>d) swap(c,d); if(a<c&&c<b&&b<d||c<a&&a<d&&d<b) { add_edge(i,other[j]); add_edge(j,other[i]); add_edge(other[i],j); add_edge(other[j],i); } }}bool DFS(int i){ vis[i]=1; for(int p=first[i];p;p=E[p].next) { int j=E[p].to; if(vis[j]) continue; if(vis[other[j]]) return 0; if(!DFS(j)) return 0; } return 1;}bool two_SAT(){ memset(vis,0,sizeof(vis)); for(int i=1;i<=M;i++) { if(vis[i]||vis[other[i]]) continue; top=0; if(!DFS(i)) { while(top) vis[stk[top--]]=0; if(!DFS(other[i])) return 0; } } return 1;}void work(){ if(M<=N*3-6&&two_SAT()) printf("YES\n"); else printf("NO\n");}int main(){ freopen("test.in","r",stdin); freopen("test.out","w",stdout); _scanf(T); for(int i=1;i<=T;i++) { data_in(); work(); } return 0;}
- hnoi2010 平面图判定 2_SAT
- 【BZOJ1997】[Hnoi2010]Planar【平面图判定】【2-SAT】
- 【hnoi2010】平面图判定
- 【平面图判定+2-SAT验证】BZOJ1997 [Hnoi2010]Planar
- BZOJ 1997: [Hnoi2010]Planar 平面图判定,TWOSAT
- bzoj 1997: [Hnoi2010]Planar 2-SAT+平面图
- [HNOI 2010] 平面图判定
- 2_SAT问题
- HDU 3622 2_SAT
- POJ 3207 2_sat
- 2_SAT问题小结
- [图论] 平面图 平面性的判定
- poj 3648 Wedding 2_SAT
- poj 2723 Get Luffy Out 2_SAT
- 平面图
- 【hnoi2010】
- poj 3683 Priest John's Busiest Day 2_sat
- [BZOJ1997][HNOI2010][2-sat]Planar
- java集合二之LinkedList
- 一个馒头引发的血案 --- 需要嵌套查询而不用嵌套查询的后果
- Leetcode
- 使用gulp创建一个项目
- MAC上搭建eclipse+android开发环境
- hnoi2010 平面图判定 2_SAT
- win10安装oracle11g出现INS-13001环境不满足最低要求
- Gift (单调队列优化dp)
- 哈理工oj 2002 幂集
- 简单的MD5加密解密
- java语言程序设计 第八章(8.35、8.36)
- Gym100548G-The Problem to Slow Down You
- 软件测试工程师应该具备的基本功底
- 听韩顺平聊PHP初学者如何变身大牛(一)?