zoukankan      html  css  js  c++  java
  • POJ 3207 2SAT

    题意:

    一个圆,圆的边上按顺时针放着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 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    写一写这几天安卓开发遇到的坑
    安卓环境搭建
    正则表达式
    一段时间的总结
    路飞-登录页面
    路飞-腾讯云短信接口
    路飞-Redis
    路飞-git操作
    路飞-后台xadmin配置
    路飞-后台处理跨域问题
  • 原文地址:https://www.cnblogs.com/proverbs/p/2666188.html
Copyright © 2011-2022 走看看