zoukankan      html  css  js  c++  java
  • bzoj 1823: [JSOI2010]满汉全席 && bzoj 2199 : [Usaco2011 Jan]奶牛议会 2-sat

    noip之前学的内容了,看到题竟然忘了怎么建图了,复习一下。

    2-sat

    大概是对于每个元素,它有0和1两种选择,必须选一个但不能同时选。这之间又有一些二元关系,比如x&y=1等等。。。

    先把每个点拆成0和1两个点。

    那么我们就建图,如果x等于A的话y必须等于B,那么从x的A点向y的B点连一条有向边,表示选了一个点它所有的后继点也必须选。

    没有一组合法解的情况当且仅当x的01两个点缩点后在同一个强联通分量里。

    bzoj 1823 

    裸题

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define N 205
     6 #define M 4005
     7 using namespace std;
     8 int n,m;
     9 int head[N],ver[M],nxt[M],tot;
    10 void add(int a,int b)
    11 {
    12     tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
    13 }
    14 int dfn[N],low[N],tim,in[N],st[N],top,cnt,be[N];
    15 void dfs(int x)
    16 {
    17     dfn[x]=low[x]=++tim;
    18     st[++top]=x;
    19     in[x]=1;
    20     for(int i=head[x];i;i=nxt[i])
    21     {
    22         if(!dfn[ver[i]])
    23         {
    24             dfs(ver[i]);
    25             low[x]=min(low[x],low[ver[i]]);
    26         }
    27         else if(in[ver[i]])
    28         {
    29             low[x]=min(low[x],dfn[ver[i]]);
    30         }
    31     }
    32     if(low[x]==dfn[x])
    33     {
    34         cnt++;int y;
    35         do
    36         {
    37             y=st[top--];
    38             be[y]=cnt;
    39             in[y]=0;
    40         }while(y!=x);
    41     }
    42     return ;
    43 }
    44 int main()
    45 {
    46     int cas;
    47     scanf("%d",&cas);
    48     while(cas--)
    49     {
    50         tim=tot=cnt=top=0;
    51         memset(be,0,sizeof(be));
    52         memset(head,0,sizeof(head));
    53         memset(dfn,0,sizeof(dfn));
    54         memset(low,0,sizeof(low));
    55         scanf("%d%d",&n,&m);
    56         char s1[10],s2[10];
    57         for(int i=1;i<=m;i++)
    58         {
    59             scanf("%s%s",s1,s2);
    60             int k1,k2;k1=k2=0;
    61             int len1=strlen(s1);
    62             for(int i=1;i<len1;i++)
    63             {
    64                 k1=k1*10+s1[i]-'0';
    65             }
    66             int len2=strlen(s2);
    67             for(int i=1;i<len2;i++)
    68             {
    69                 k2=k2*10+s2[i]-'0';
    70             }
    71             int op1,op2;
    72             if(s1[0]=='m')op1=1;else op1=0;
    73             if(s2[0]=='m')op2=1;else op2=0;
    74             add(k1+(op1^1)*n,k2+op2*n);
    75             add(k2+(op2^1)*n,k1+op1*n);
    76         }
    77         for(int i=1;i<=2*n;i++)if(!dfn[i])dfs(i);
    78         bool flag=0;
    79         for(int i=1;i<=n;i++)if(be[i]==be[i+n])flag=1;
    80         if(flag)puts("BAD");
    81         else puts("GOOD");
    82     }
    83     return 0;
    84 }
    View Code

    bzoj 2199

    按2-sat建完图之后,从每个点开始dfs一遍。

    如果一个点能访问到它的对立点说明这个点不能选。

    如果x的两个点都不能选说明无解,相当于在同一个强联通分量里。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define N 2005
     6 #define M 8005
     7 using namespace std;
     8 int n,m;
     9 int head[N],ver[M],nxt[M],tot;
    10 void add(int a,int b)
    11 {
    12     tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
    13 }
    14 int ans[N];
    15 int v[N];
    16 void dfs(int x)
    17 {
    18     v[x]=1;
    19     for(int i=head[x];i;i=nxt[i])
    20     {
    21         if(!v[ver[i]])dfs(ver[i]);
    22     }
    23 }
    24 int main()
    25 {
    26     scanf("%d%d",&n,&m);
    27     char s1[3],s2[3];
    28     int t1,t2;
    29     for(int i=1;i<=m;i++)
    30     {
    31         scanf("%d",&t1);scanf("%s",s1);
    32         scanf("%d",&t2);scanf("%s",s2);
    33         int op1,op2;
    34         if(s1[0]=='Y')op1=1;else op1=0;
    35         if(s2[0]=='Y')op2=1;else op2=0;
    36         add(t1+(op1^1)*n,t2+op2*n);
    37         add(t2+(op2^1)*n,t1+op1*n);
    38     }
    39     bool flag=0;
    40     for(int i=1;i<=n;i++)
    41     {
    42         int now=0;
    43         memset(v,0,sizeof(v));
    44         dfs(i);
    45         if(v[i+n])now++;
    46         memset(v,0,sizeof(v));
    47         dfs(i+n);
    48         if(v[i])now+=2;
    49         ans[i]=now;
    50         if(now==3)flag=1;
    51     }
    52     if(flag)puts("IMPOSSIBLE");
    53     else
    54     {
    55         for(int i=1;i<=n;i++)
    56         {
    57             if(!ans[i])putchar('?');
    58             else if(ans[i]==1)putchar('Y');
    59             else putchar('N');
    60         }
    61     }
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    [POI2013]LUK-Triumphal arch
    [CF1149C](Tree Generator)
    NOI2018归程
    [CF191](Fools and Roads)
    [CF700E](Cool Slogans)
    我石乐志
    想题的时候不要颓废
    人不能忘耻
    反思
    中考加油!
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6609642.html
Copyright © 2011-2022 走看看