POJ 3207 2-SAT

题意:

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

 

思路:

把每条边都抽象成一个点a,再把a点拆成两个点(2-SAT嘛),分别为a0和a1,分别表示这条边从内部连何从外部连,说到这里应该会建图了吧!

再提示一下,对于有可能交叉的两条边考虑连边。怎么判断有可能交叉大家都会吧,细心点就是了!

 

 

View Code
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 #define N 30000
 6 #define M 1500000
 7 using namespace std;
 8 int head[N],next[M],to[M],belong[N],dfn[N],low[N],n,m,t,p,divg,cnt,a[M],b[M],stack[N];
 9 bool fg[N];
10 void read()
11 {
12     memset(head,-1,sizeof head);cnt=0;
13     memset(belong,0,sizeof belong);
14     memset(dfn,0,sizeof dfn);
15     memset(fg,0,sizeof fg);
16     t=0; p=0; divg=0;
17     for(int i=1;i<=m;i++)
18     {
19         scanf("%d%d",&a[i],&b[i]);
20         if(a[i]>b[i]) swap(a[i],b[i]);
21     }
22 }
23 inline void add(int u,int v)
24 {
25     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
26 }
27 bool judge(int x,int y)
28 {
29     if(a[x]>a[y]&&a[x]<b[y]&&b[x]>b[y]) return true;
30     if(a[y]>a[x]&&a[y]<b[x]&&b[y]>b[x]) return true;
31     return false;
32 }
33 void create()
34 {
35     for(int i=1;i<=m;i++)
36         for(int j=i+1;j<=m;j++)
37             if(judge(i,j))
38                 add(i+m,j),add(j,i+m),add(i,j+m),add(j+m,i);
39 }
40 void dfs(int u)
41 {
42     t++;
43     dfn[u]=low[u]=t;
44     stack[++p]=u; fg[u]=true;
45     for(int i=head[u];~i;i=next[i])
46     {
47         if(!dfn[to[i]])
48         {
49             dfs(to[i]);
50             low[u]=min(low[u],low[to[i]]);
51         }
52         else if(fg[to[i]]) low[u]=min(low[u],dfn[to[i]]);
53     }
54     if(dfn[u]==low[u])
55     {
56         divg++;
57         int tmp=-1;
58         while(tmp!=u)
59         {
60             tmp=stack[p--];
61             belong[tmp]=divg;
62             fg[tmp]=false;
63         }
64     }
65 }
66 bool check()
67 {
68     for(int i=1;i<=m;i++)
69         if(belong[i]==belong[i+m]) return false;
70     return true;
71 }
72 void tarjan()
73 {
74     for(int i=1;i<=m+m;i++)
75         if(!dfn[i]) dfs(i);
76     if(check()) printf("panda is telling the truth...\n");
77     else printf("the evil panda is lying again\n");
78 }
79 int main()
80 {
81     while(scanf("%d%d",&n,&m)!=EOF)
82     {
83         read();
84         create();
85         tarjan();
86     }
87     return 0;
88 }

 

 

posted @ 2012-08-31 23:37  proverbs  阅读(229)  评论(0编辑  收藏  举报