poj 3207 Ikki's Story IV Panda's Trick (2sat)

http://poj.org/problem?id=3207

题意:

平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,使这些边都不相交。

解题报告:

题意可能刚开始不是很好理解,比如1 5连边,2,6连边,由于点是顺序排列的,一画图就可以发现,这两条边必须一个从圆外面连,一个从内部连,否则就会相交。如果再加入3 7这条边,那么就必须相交了。

这样,就可以转化成标准的2-sta问题:

1:每个边看成2个点:分别表示在内部连接和在外部连接,只能选择一个。计作点i和点i'

2:如果两条边i和j必须一个画在内部,一个画在外部(一个简单判断就可以)

那么连边:

i->j’, 表示i画内部的话,j只能画外部,即j’

j->i’,同理

i’->j,同理

j’->i,同理

然后就是2-sat算法了,tarjan一下,如果有i和i'同属于一个强联通,返回false,否则就成立。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include<string>
 11 #define Min(a,b) a<b?a:b
 12 #define Max(a,b) a>b?a:b
 13 #define CL(a,num) memset(a,num,sizeof(a));
 14 #define eps  1e-12
 15 #define inf 100000000
 16 #define mx 1<<60
 17 #define ll   __int64
 18 const double pi  = acos(-1.0);
 19 const int maxn = 300000;
 20 using namespace std;
 21 int  top,num,bcnt,belong[maxn],instack[maxn],stack[maxn],dfn[maxn],low[maxn];
 22 int n ,m;
 23 struct node
 24 {
 25     int x,y;
 26 
 27 }a[maxn];
 28 struct pnode
 29 {
 30     int to;
 31     int next;
 32 }p[maxn];
 33 
 34 int cnt ,next[maxn];
 35 void add(int u,int v)
 36 {
 37     p[cnt].to = v;
 38     p[cnt].next  = next[u];
 39     next[u] = cnt++;
 40 
 41 }
 42 void tarjan(int i)
 43 {
 44     int j,k;
 45     dfn[i] = low[i] = ++num;
 46     stack[++top] = i;
 47     instack[i] = 1;
 48     for(k = next[i] ; k != -1;k = p[k].next)
 49     {
 50 
 51          j = p[k].to ;
 52         if(!dfn[j])
 53         {
 54             tarjan(j);
 55             if(low[j] < low[i]) low[i] = low[j] ;
 56         }
 57         else
 58         {
 59             if(instack[j] && dfn[j] < low[i]) low[i] = dfn[j] ;
 60         }
 61 
 62     }
 63     if(dfn[i] == low[i])
 64     {
 65         bcnt++;
 66         do
 67         {
 68             j = stack[top--];
 69             instack[j] = 0 ;
 70             belong[j] = bcnt ;
 71         }while(j != i);
 72     }
 73 }
 74 void solve()
 75 {
 76     int i, l;
 77     for(i =0 ; i <= m*2;i++)
 78     {
 79         dfn[i] = low[i] = instack[i] = stack[i] = belong[i] = 0;
 80     }
 81     top = bcnt = num = 0;
 82     for(i = 0 ; i < 2*m;i++)
 83     {
 84         if(!dfn[i])tarjan(i);
 85     }
 86     bool f = true ;
 87     for(i = 0 ;  i < m;i++)
 88     {
 89 
 90         if(belong[i] == belong[i+m])
 91         {
 92 
 93             f = false ;
 94             break ;
 95         }
 96     }
 97 
 98     if(f) printf("panda is telling the truth...\n");
 99     else
100       printf("the evil panda is lying again\n");
101 }
102 void init()
103 {
104     CL(next,-1);
105     cnt = 0 ;
106 
107 }
108 int main()
109 {
110     int i,j;
111     //freopen("data.txt","r",stdin) ;
112     while(scanf("%d%d",&n,&m)!=EOF)
113     {
114         init();
115         for(i = 0 ; i < m;i++)
116         {
117             scanf("%d%d",&a[i].x,&a[i].y);
118             if(a[i].x > a[i].y) swap(a[i].x,a[i].y);
119         }
120         for(i = 0 ; i < m;i++ )
121         {
122             for(j = i+1;j<m;j++)
123             {
124                 if(a[i].x < a[j].x && a[j].x < a[i].y &&a[i].y < a[j].y|| a[j].x<a[i].x&&a[i].x < a[j].y &&a[j].y < a[i].y)//判断是否相交
125                 {
126                     add(i,j + m);
127                     add(j + m,i);
128                     add(i + m,j);
129                     add(j ,i + m) ;
130                 }
131             }
132         }
133         solve();
134 
135 
136     }
137 
138 }
 

原文地址:https://www.cnblogs.com/acSzz/p/2672481.html