【2-SAT(tarjan)】BZOJ1997-[Hnoi2010]Planar

【题目大意】
给出一张存在哈密顿回路的无向图,判断是否是平面图。
【思路】
首先平面图的一个性质:边数<=点数*3-6
因为存在哈密顿回路,可以将回路看作是一个圆,考量不再哈密顿回路中的边。如果两天边相交(判断相交可以随意yy一下),那么必然一条在圆内一条在圆外,显然是2-SAT。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<stack>
  7 using namespace std;
  8 const int MAXN=20000+50;
  9 int n,m;
 10 int u[MAXN],v[MAXN],pos[MAXN];
 11 vector<int> E[MAXN];
 12 int dfn[MAXN],low[MAXN],instack[MAXN],col[MAXN],cnt,colcnt;
 13 stack<int> S;
 14  
 15 int cross(int i,int j)
 16 {
 17     int x1=pos[u[i]],y1=pos[v[i]],x2=pos[u[j]],y2=pos[v[j]]; 
 18     if ((x1<x2 && x2<y1 && y1<y2) || (x2<x1 && x1<y2 && y2<y1)) return 1;else return 0;
 19 }
 20  
 21 void addedge(int u,int v)
 22 {
 23     E[u].push_back(v);
 24     E[v].push_back(u);
 25 }
 26  
 27  
 28 void tarjan(int u)
 29 {
 30     dfn[u]=low[u]=++cnt;
 31     S.push(u);
 32     instack[u]=1;
 33       
 34     for (int i=0;i<E[u].size();i++)
 35     {
 36         int son=E[u][i];
 37         if (!instack[son])
 38         {
 39             tarjan(son);
 40             low[u]=min(low[son],low[u]);
 41         }
 42         else
 43         if (instack[son]==1)
 44             low[u]=min(dfn[son],low[u]);
 45     }
 46       
 47     if (dfn[u]==low[u])
 48     {
 49         colcnt++;
 50         int x;
 51         do
 52         {
 53              x=S.top();
 54              S.pop();
 55              col[x]=colcnt;
 56              instack[x]=2;
 57         }while (x!=u);
 58     }
 59 } 
 60  
 61  
 62 void init()
 63 {
 64     scanf("%d%d",&n,&m);
 65     cnt=0,colcnt=0;
 66     for (int i=0;i<MAXN;i++) vector<int>().swap(E[i]);//注意不要忘记清空 
 67     memset(instack,0,sizeof(instack));
 68     for (int i=1;i<=m;i++)
 69         scanf("%d%d",&u[i],&v[i]);
 70     for (int i=1;i<=n;i++)
 71     {
 72         int x;
 73         scanf("%d",&x);
 74         pos[x]=i;
 75     }
 76 }
 77  
 78 void build()
 79 {
 80     for (int i=1;i<=m;i++)
 81         if (pos[u[i]]>pos[v[i]]) swap(u[i],v[i]);
 82     for (int i=1;i<=m;i++)
 83         for (int j=i+1;j<=m;j++)
 84             if (cross(i,j))
 85             {
 86                 addedge(i,j+m);
 87                 addedge(i+m,j);
 88             }
 89 }
 90  
 91 void solve()
 92 {
 93     for (int i=1;i<=2*m;i++) if (!instack[i]) tarjan(i);
 94     int f=1;
 95     for (int i=1;i<=m;i++)
 96         if (col[i]==col[i+m])
 97         {
 98             f=0;
 99             break;
100         }
101     if (f) cout<<"YES"<<endl;
102         else cout<<"NO"<<endl;
103 }
104  
105 int main()
106 {
107     int T;
108     scanf("%d",&T);
109     while (T--)
110     {
111         init();
112         if (m<=3*n-6)//平面图定理 
113         {
114             build();
115             solve();
116         }
117         else
118             cout<<"NO"<<endl;
119     }
120     return 0;   
121 } 

 

posted @ 2016-07-17 23:14  iiyiyi  阅读(120)  评论(0编辑  收藏  举报