【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 }