2-SAT[JSOI2010]满汉全席

Posted zhenglw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 Judgeint 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 

以上是关于2-SAT[JSOI2010]满汉全席的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ_1823_[JSOI2010]满汉全席_2-sat+tarjan

[JSOI2010]满汉全席 2-SAT

BZOJ1823[JSOI2010]满汉全席 2-SAT

BZOJ1823 [JSOI2010]满汉全席 2-sat

Luogu P4171 [JSOI2010]满汉全席(2-SAT)

题解JSOI2010满汉全席