题目大意:给出一个无向图,保证这个图有哈密顿回路,求这个图是不是平面图。
思路:平面图的判定条件之一:如果边数大于点数*3+6那么这个图一定不是平面图。这算是一个强剪枝吧。
我们把图中哈密顿回路的这个环上的边去掉,就变成了判定边能否不想交的2-SAT问题,POJ好像有一个原题来着。建图方法我就不说了,相信大家看到2-SAT就知道怎么写了。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 10010 using namespace std; struct Edge{ int x,y; Edge(int _,int __):x(_),y(__) {} Edge() {} void Read() { scanf("%d%d",&x,&y); } }edge[MAX],stack[MAX]; int top; int cases,points,edges; int C[MAX]; inline bool Judge(const Edge &a,const Edge &b) { return b.x > a.x && b.x < a.y && b.y > a.y; } namespace II_SAT{ int head[MAX],total; int next[819200],aim[819200]; int dfn[MAX],low[MAX],_clock; int stack[MAX],top; bool in_stack[MAX]; int changed[MAX],scc; void Initialize() { total = _clock = scc = top = 0; memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(in_stack,false,sizeof(in_stack)); } void Add(int x,int y) { next[++total] = head[x]; aim[total] = y; head[x] = total; } void Tarjan(int x) { dfn[x] = low[x] = ++_clock; stack[++top] = x; in_stack[x] = true; for(int i = head[x]; i; i = next[i]) { if(!dfn[aim[i]]) Tarjan(aim[i]),low[x] = min(low[x],low[aim[i]]); else if(in_stack[aim[i]]) low[x] = min(low[x],dfn[aim[i]]); } if(dfn[x] == low[x]) { ++scc; int temp; do { temp = stack[top--]; in_stack[temp] = false; changed[temp] = scc; }while(temp != x); } } } int main() { for(cin >> cases; cases--;) { scanf("%d%d",&points,&edges); for(int i = 1; i <= edges; ++i) edge[i].Read(); for(int x,i = 1; i <= points; ++i) { scanf("%d",&x); C[x] = i; } if(edges > 3 * points + 6) { puts("NO"); continue; } top = 0; for(int i = 1; i <= edges; ++i) { int s = C[edge[i].x],t = C[edge[i].y]; if(s > t) swap(s,t); if(!((s + 1 == t) || (s == 1 && t == points))) stack[++top] = Edge(s,t); } II_SAT::Initialize(); for(int i = 1; i <= top; ++i) for(int j = i + 1; j <= top; ++j) if(Judge(stack[i],stack[j]) || Judge(stack[j],stack[i])) { II_SAT::Add(i << 1,j << 1|1); II_SAT::Add(j << 1|1,i << 1); II_SAT::Add(j << 1,i << 1|1); II_SAT::Add(i << 1|1,j << 1); } for(int i = 2; i <= (top << 1|1); ++i) if(!II_SAT::dfn[i]) II_SAT::Tarjan(i); bool flag = true; for(int i = 1; i <= top; ++i) if(II_SAT::changed[i << 1] == II_SAT::changed[i << 1|1]) { flag = false; break; } puts(&"NO\0YES"[flag * 3]); } return 0; }
时间: 2024-10-17 06:22:41