• 【2-SAT】[JSOI2010]满汉全席


    感觉方法和题解差不多,但是题解写的好烦啊...也不是烦,就是很复杂

    这里建议开一个数组表示当前这个点选或者不选的编号,这样之后自己理思路也会清楚一点

    然而我调了一个小时才发现我是Tarjan写错了......

    这道题对于每一个菜分两种情况讨论,每一种情况又有选和不选两种方案

    所以相当于每一个菜可以拆成4个点 

      1.做法M-选

      2.做法M-不选

      3.做法H-选

      4.做法H-不选

    显然题目里给的条件是或,但是不只是有题目里给的条件,还有隐含条件:一道菜只能有一种做法!

    然后按照2-sat的套路就好了

    代码里$bb[i][j][k]$数组表示当前是第i道菜,做法是j:1/2,选或者不选是k:0/1

    这样之后加边的时候会很简洁明了

     1 #include<bits/stdc++.h>
     2 #define writeln(x)  write(x),puts("")
     3 #define writep(x)   write(x),putchar(' ')
     4 using namespace std;
     5 inline int read(){
     6     int ans=0,f=1;char chr=getchar();
     7     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
     8     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
     9     return ans*f;
    10 }void write(int x){
    11     if(x<0) putchar('-'),x=-x;
    12     if(x>9) write(x/10);
    13     putchar(x%10+'0');
    14 }const int M = 2e4+5;
    15 int head[M],nxt[M],ver[M],tot,T,n,m,bb[M][3][3],dfn[M],low[M],ins[M],sta[M],top,color,col[M];
    16 char s1[M],s2[M];
    17 struct Judge{int type[2],x[2];}J[M];
    18 inline void add(int x,int y){ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;}
    19 void Tarjan(int x){
    20     dfn[x]=low[x]=++T;ins[x]=1;sta[top++]=x;
    21     for(int i=head[x];i;i=nxt[i]){
    22         if(!dfn[ver[i]])Tarjan(ver[i]),low[x]=min(low[x],low[ver[i]]);
    23         else if(ins[ver[i]]==1) low[x]=min(low[x],dfn[ver[i]]);
    24     }if(low[x]==dfn[x]){++color;
    25         do{    col[sta[--top]]=color;
    26             ins[sta[top]]=-1;
    27         }while(sta[top]!=x);
    28     }return;
    29 }inline void Init(){
    30     memset(low,0,sizeof(low)),memset(dfn,0,sizeof(dfn)),memset(ins,0,sizeof(ins));
    31     memset(col,0,sizeof(col)),memset(head,0,sizeof(head));tot=T=color=0;
    32     n=read(),m=read();
    33     for(int i=1;i<=m;i++){
    34         scanf("%s%s",s1,s2);
    35         int l1=strlen(s1),l2=strlen(s2);
    36         if(s1[0]=='m')J[i].type[0]=1;else J[i].type[0]=2;
    37         if(s2[0]=='m')J[i].type[1]=1;else J[i].type[1]=2;
    38         int p=1,ans=0;
    39         while(isdigit(s1[p])&&p<=l1){ans=(ans<<3)+(ans<<1)+s1[p]-48;++p;}
    40         J[i].x[0]=ans;p=1,ans=0;
    41         while(isdigit(s2[p])&&p<=l2){ans=(ans<<3)+(ans<<1)+s2[p]-48;++p;}
    42         J[i].x[1]=ans;
    43     }return;
    44 }inline void Make_Graph(){
    45     for(int i=1;i<=n;i++)bb[i][1][1]=i,bb[i][1][0]=n+i,bb[i][2][1]=2*n+i,bb[i][2][0]=3*n+i;
    46     for(int i=1;i<=m;i++){
    47         int x=J[i].type[0],a=J[i].x[0],y=J[i].type[1],b=J[i].x[1];
    48         add(bb[a][x][0],bb[b][y][1]),add(bb[b][y][0],bb[a][x][1]);
    49         add(bb[i][1][1],bb[i][2][0]),add(bb[i][2][1],bb[i][1][0]);
    50     }
    51 }inline void Solve(){
    52     for(int i=1;i<=n*4;i++)if(!dfn[i])Tarjan(i);
    53     for(int i=1;i<=n;i++)if(col[bb[i][1][0]]==col[bb[i][1][1]]||col[bb[i][2][1]]==col[bb[i][2][0]])return puts("BAD"),void();
    54     puts("GOOD");
    55 }int main(){
    56     int T=read();
    57     while(T--)Init(),Make_Graph(),Solve();
    58     return 0;
    59 }
  • 相关阅读:
    opencvsharp BitmapSource图片截取问题
    wpf RenderTargetBitmap保存控件为图片时图片尺寸不对的问题
    c# ??和运算符先后的问题
    wpf 窗口打开后默认设置控件焦点
    win10 requireAdministrator设置开机自启动无效的解决方案
    Gogs webhook钩子 验签 (PHP版本)
    MongoDB管理用户的认证机制
    RocketMQ使用指南及参数详解
    微信公众号h5获取用户openId的方法和步骤
    php中常用的正则表达式函数
  • 原文地址:https://www.cnblogs.com/zhenglw/p/11627289.html
Copyright © 2020-2023  润新知