[BZOJ 1997][Hnoi2010]Planar
1997: [Hnoi2010]Planar
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 2167 Solved: 804
[Submit][Status][Discuss]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
YESHINT
Source
题解
思路非常清奇...
首先图里存在哈密顿回路而且输入中已经给出, 那么如果要判断这个图是否是平面图, 我们首先一定会把这个哈密顿回路画在上面, 而且这部分没有优化余地.
然后剩下的不在环上的边则有两种选择: 从环里穿过去或者从环外绕过去. 根据边所连接的两个节点在哈密顿回路中的顺序确定如果边同时在环内是否会相交, 如果会相交的话这两条边必须分居哈密顿环两侧. 处理出所有之后判断可行性就好了
所以这个充满 $NPC$ 问题的题面实际上是个 $2-SAT$ ...QAQ
然后就是 $2-SAT$ 要加反向边(NOI 2017的惨痛教训)
参考代码
1 #include <stack> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <iostream> 6 #include <algorithm> 7 8 const int MAXEX=1e6+10; 9 const int MAXE=1e4+10; 10 const int MAXV=2e3+10; 11 12 struct Edge{ 13 int from; 14 int to; 15 Edge* next; 16 }; 17 Edge E[MAXE]; 18 Edge Ex[MAXEX]; 19 Edge* head[MAXV]; 20 Edge* top=E; 21 22 int v; 23 int e; 24 int clk; 25 int scc; 26 int dfn[MAXV]; 27 int low[MAXV]; 28 int pos[MAXV]; 29 int cycle[MAXV]; 30 int belong[MAXV]; 31 32 bool inStack[MAXV]; 33 34 std::stack<int> s; 35 36 void Tarjan(int); 37 void Initialize(); 38 void Insert(int,int); 39 40 int main(){ 41 int T; 42 scanf("%d",&T); 43 while(T--){ 44 Initialize(); 45 if(e>3*v-6){ 46 puts("NO"); 47 continue; 48 } 49 int cnt=0; 50 for(int i=0;i<e;i++){ 51 E[i].from=pos[E[i].from]; 52 E[i].to=pos[E[i].to]; 53 if(E[i].from>E[i].to) 54 std::swap(E[i].from,E[i].to); 55 if(E[i].to-E[i].from==1||E[i].from==1&&E[i].to==v) 56 continue; 57 else 58 E[cnt++]=E[i]; 59 } 60 for(int i=0;i<cnt;i++){ 61 for(int j=i+1;j<cnt;j++){ 62 if((E[i].from<E[j].from&&E[i].to<E[j].to&&E[i].to>E[j].from)||(E[i].from>E[j].from&&E[i].to>E[j].to&&E[i].from<E[j].to)){ 63 Insert(2*i+1,2*j); 64 Insert(2*i,2*j+1); 65 Insert(2*j+1,2*i); 66 Insert(2*j,2*i+1); 67 } 68 } 69 } 70 for(int i=0;i<2*cnt;i++){ 71 if(dfn[i]==0) 72 Tarjan(i); 73 } 74 bool ans=true; 75 for(int i=0;i<cnt;i++){ 76 if(belong[2*i]==belong[2*i+1]){ 77 ans=false; 78 break; 79 } 80 } 81 if(ans) 82 puts("YES"); 83 else 84 puts("NO"); 85 } 86 return 0; 87 } 88 89 inline void Insert(int from,int to){ 90 top->from=from; 91 top->to=to; 92 top->next=head[from]; 93 head[from]=top++; 94 } 95 96 void Tarjan(int root){ 97 dfn[root]=low[root]=++clk; 98 inStack[root]=true; 99 s.push(root); 100 for(Edge* i=head[root];i!=NULL;i=i->next){ 101 if(dfn[i->to]==0){ 102 Tarjan(i->to); 103 low[root]=std::min(low[root],low[i->to]); 104 } 105 else if(inStack[i->to]) 106 low[root]=std::min(low[root],dfn[i->to]); 107 } 108 if(low[root]==dfn[root]){ 109 scc++; 110 int top; 111 do{ 112 top=s.top(); 113 belong[top]=scc; 114 inStack[top]=false; 115 s.pop(); 116 }while(top!=root); 117 } 118 } 119 120 inline void Initialize(){ 121 memset(head,0,sizeof(head)); 122 memset(low,0,sizeof(low)); 123 memset(dfn,0,sizeof(dfn)); 124 clk=scc=0; 125 top=Ex; 126 scanf("%d%d",&v,&e); 127 for(int i=0;i<e;i++){ 128 scanf("%d%d",&E[i].from,&E[i].to); 129 } 130 for(int i=1;i<=v;i++){ 131 scanf("%d",cycle+i); 132 pos[cycle[i]]=i; 133 } 134 }
本博客已弃用, 新个人主页: https://rvalue.moe, 新博客: https://blog.rvalue.moe