【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 }
原文地址:https://www.cnblogs.com/zhenglw/p/11627289.html