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 }

 

 

你可能感兴趣的:(poj)