• [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
    YES

    HINT

     

    Source

    题解

    思路非常清奇...

    首先图里存在哈密顿回路而且输入中已经给出, 那么如果要判断这个图是否是平面图, 我们首先一定会把这个哈密顿回路画在上面, 而且这部分没有优化余地.

    然后剩下的不在环上的边则有两种选择: 从环里穿过去或者从环外绕过去. 根据边所连接的两个节点在哈密顿回路中的顺序确定如果边同时在环内是否会相交, 如果会相交的话这两条边必须分居哈密顿环两侧. 处理出所有之后判断可行性就好了

    所以这个充满 $NPC$ 问题的题面实际上是个 $2-SAT$ ...QAQ

    然后就是 $2-SAT$ 要加反向边(NOI 2017的惨痛教训)

    参考代码

    GitHub

      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 }
    Backup

  • 相关阅读:
    大宗商品经营管理特点与风险节点
    大宗商品企业风险管理与套期会计课程
    推荐一个php7+ mongodb三方类
    利用Redis锁解决高并发问题
    PHP socket初探 --- 关于IO的一些枯燥理论
    Swoole 4.1.0 正式版发布,支持原生 Redis/PDO/MySQLi 协程化
    PHP利用Mysql锁解决高并发
    PHP AES cbc模式 pkcs7 128加密解密
    PHP 利用文件锁处理高并发
    Redis 应用场景【商品拼团抢购】
  • 原文地址:https://www.cnblogs.com/rvalue/p/7667195.html
Copyright © 2020-2023  润新知