• POJ 2723 2SAT


    题意:

    有2n把钥匙,每2个一组,给你每组的钥匙信息,并且每组的钥匙只能用一个。有m个门,每个门有2个锁,只要打开一个锁这个门就开了。问你最多能够打开多少个门。

    PS:打开门必须是有序的,即你想要打开i就必须之前已经打开了i-1

    分析:

    不知道我这样做的人多不多。

    由于有序性,所以二份答案是必须的

    我是把一个钥匙a(不是一组钥匙)拆成两个点a0和a1,分别表示没有取过和取过,对于和他同组的钥匙b,连两条边,a1-->b0和b1-->a0,表示取了a钥匙就不能再取b钥匙

    对于每层的两把锁,c和d,连c0-->d1,d0-->c1,表示c钥匙不取则d钥匙必须取,d钥匙不取则c钥匙必须取,也就是说,必须要有一个钥匙来开这个锁

    View Code
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <iostream>
     5 using namespace std;
     6 const int N=(1<<13)+100000;
     7 const int M=(1<<25)+1000000;
     8 int head[N],next[M],to[M],dir[N],ans,n,m,cnt,dfn[N],low[N],belong[N],mid,stack[N],p,divg,t,do1[M],do2[M];
     9 bool fg[N];
    10 void read()
    11 {
    12     for(int i=1,a,b;i<=n;i++)
    13     {
    14         scanf("%d%d",&a,&b),a++,b++;
    15         dir[a]=b,dir[b]=a;
    16     }
    17     for(int i=1;i<=m;i++) scanf("%d%d",&do1[i],&do2[i]),do1[i]++,do2[i]++;
    18 }
    19 inline void add(int u,int v)
    20 {
    21     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
    22 }
    23 void create()
    24 {
    25     memset(head,-1,sizeof head);
    26     memset(dfn,0,sizeof dfn);
    27     memset(belong,0,sizeof belong);
    28     memset(fg,0,sizeof fg);
    29     cnt=0; divg=0; p=0; t=0;
    30     for(int i=1;i<=2*n;i++) add(i,dir[i]+2*n);
    31     for(int i=1;i<=mid;i++)
    32         add(do1[i]+2*n,do2[i]),add(do2[i]+2*n,do1[i]);
    33 }
    34 bool judge()
    35 {
    36     for(int i=1;i<=2*n;i++)
    37         if(belong[i]==belong[i+2*n]) return false;
    38     return true;
    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 tarjan()
    67 {
    68     create();
    69     for(int i=1;i<=4*n;i++)
    70         if(!dfn[i]) dfs(i);
    71     if(judge()) return true;
    72     else return false;
    73 }
    74 void go()
    75 {
    76     int l=0,r=m;
    77     while(l<=r)
    78     {
    79         mid=(l+r)>>1;
    80         //printf("%d\n",mid);
    81         if(tarjan()) ans=mid,l=mid+1;
    82         else r=mid-1;
    83     }
    84     printf("%d\n",ans);
    85 }
    86 int main()
    87 {
    88     while(scanf("%d%d",&n,&m),n||m)
    89     {
    90         read();
    91         go();
    92     }
    93     system("pause");
    94     return 0;
    95 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    第十二周总结
    第十一周课程总结
    2020软件工程作业02
    2020软件工程第一次作业
    2019年春季学期总结
    2019年春第四次程序设计实验报告
    2019年春第一次程序设计实验报告
    2019年春第三次程序设计实验报告
    第二次课程设计实验报告
    第十二周作业
  • 原文地址:https://www.cnblogs.com/proverbs/p/2667015.html
Copyright © 2020-2023  润新知