【BZOJ1823】【JSOI2010】满汉全席
差点忘了2-sat……
原题:
满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中。由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉全席,而能够烹饪出经过专家认证的满汉全席,也是中国厨师最大的荣誉之一。 世界满汉全席协会是由能够料理满汉全席的专家厨师们所组成,而他们之间还细分为许多不同等级的厨师。为了招收新进的厨师进入世界满汉全席协会,将于近日举办满汉全席大赛,协会派遣许多会员当作评审员,为的就是要在參赛的厨师之中,找到满汉料理界的明日之星。 大会的规则如下:每位參赛的选手可以得到n 种材料,选手可以自由选择用满式或是汉式料理将材料当成菜肴。大会的评审制度是:共有m 位评审员分别把关。每一位评审员对于满汉全席有各自独特的見解,但基本见解是,要有兩样菜色作为满汉全席的标志。如某评审认为,如果没有汉式东坡肉跟满式的涮羊肉锅,就不能算是满汉全席。但避免过于有主見的审核,大会规定一个评审员除非是在认为必备的两样菜色都没有做出來的狀况下,才能淘汰一位选手,否则不能淘汰一位參赛者。换句话說,只要參赛者能在这兩种材料的做法中,其中一个符合评审的喜好即可通过该评审的审查。如材料有猪肉,羊肉和牛肉时,有四位评审员的喜好如下表: 评审一 评审二 评审三 评审四 满式牛肉 满式猪肉 汉式牛肉 汉式牛肉 汉式猪肉 满式羊肉 汉式猪肉 满式羊肉 如參赛者甲做出满式猪肉,满式羊肉和满式牛肉料理,他将无法满足评审三的要求,无法通过评审。而參赛者乙做出汉式猪肉,满式羊肉和满式牛肉料理,就可以满足所有评审的要求。 但大会后來发现,在这样的制度下如果材料选择跟派出的评审员没有特别安排好的话,所有的參赛者最多只能通过部分评审员的审查而不是全部,所以可能会发生没有人通过考核的情形。如有四个评审员喜好如下表时,则不論參赛者采取什么样的做法,都不可能通过所有评审的考核: 评审一 评审二 评审三 评审四 满式羊肉 满式猪肉 汉式羊肉 汉式羊肉 汉式猪肉 满式羊肉 汉式猪肉 满式猪肉 所以大会希望有人能写一个程序來判断,所选出的m 位评审,会不会发生 没有人能通过考核的窘境,以便协会组织合适的评审团。
n≤100,m≤1000
恩题意比较难懂,简单说就是总共n个菜,每个菜都可以做成满风格或汉风格,每个评委要求两个菜a,b和各自的风格x,y,表示如果想通过他,那么做出来的菜必须满足"a菜是x风格"或"b菜必须是y风格"其中一个
某个厨师可以选择第i个菜做成满还是汉,然后如果他做的菜能通过所有评委就可以通过,否则gg
然后问你有没有方案能通过
然后就很明显了,把x菜的汉做法定为x,满做法定为x',如果某个评委要求x,y',就给x'->y'连边,y->x连边
这表示如果选了x',就不满足第一个要求,就必须选y'来满足第二个要求,y->x同理
(突然发现这个其实就是或模型吧= =)
第一次想这个建图的时候差点没想出来……果然还是练得少,掌握的不熟练
写这题的时候第一次交WA了,因为如果把所有点id-1然后用i<<1|1表示,点的值域是[0,n*2),如果用(i<<1)-1是[1,n*2],但是我第一次写的时候值域是[0,(n-1)*2]
时间有点晚,脑子有点晕……
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int rd(){int z=0,mk=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')mk=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 10 return z*mk; 11 } 12 struct ddd{int nxt,y;}e[21000]; int lk[1100],ltp=0; 13 inline void ist(int x,int y){ e[++ltp].nxt=lk[x],lk[x]=ltp,e[ltp].y=y;} 14 int n,m; 15 int dfn[1100],low[1100],dfncnt=0; 16 int stck[1100],tp=0; bool vstd[1100]; 17 int grp[1100],grpcnt=0; 18 void tj(int x){ 19 dfn[x]=low[x]=++dfncnt; stck[++tp]=x,vstd[x]=true; 20 for(int i=lk[x];i;i=e[i].nxt){ 21 if(!dfn[e[i].y]) tj(e[i].y),low[x]=min(low[x],low[e[i].y]); 22 else if(vstd[e[i].y]) low[x]=min(low[x],dfn[e[i].y]); 23 } 24 if(dfn[x]==low[x]){ 25 ++grpcnt; int tmp=-1; 26 while(tmp!=x) tmp=stck[tp--],vstd[tmp]=false,grp[tmp]=grpcnt; 27 } 28 } 29 bool gtch(){ char ch=getchar(); while(ch!='m' && ch!='h') ch=getchar(); return ch=='m';} 30 void clr(){ grpcnt=0; dfncnt=0,memset(dfn,0,sizeof(dfn)),memset(low,0,sizeof(low)); ltp=0,memset(lk,0,sizeof(lk));} 31 int main(){//freopen("ddd.in","r",stdin); 32 memset(vstd,0,sizeof(vstd)); 33 int T; cin>>T; while(T--){ clr(); 34 cin>>n>>m; 35 int l1,l2,r1,r2; 36 while(m--){ 37 l1=gtch(),r1=rd()-1,l2=gtch(),r2=rd()-1; 38 ist(r1<<1|l1,r2<<1|(l2^1)),ist(r2<<1|l2,r1<<1|(l1^1)); 39 } 40 for(int i=0;i<n*2;++i)if(!dfn[i]) tj(i); 41 bool flg=true; 42 for(int i=0;i<n;++i)if(grp[i<<1]==grp[i<<1|1]){ flg=false; break;} 43 /*while(m--){ 44 l1=gtch(),r1=rd(),l2=gtch(),r2=rd(); 45 ist((r1<<1)-l1,(r2<<1)-(l2^1)),ist((r2<<1)-l2,(r1<<1)-(l1^1)); 46 } 47 for(int i=1;i<=n*2;++i)if(!dfn[i]) tj(i); 48 bool flg=true; 49 for(int i=1;i<=n;++i)if(grp[i<<1]==grp[(i<<1)-1]){ flg=false; break;}*/ 50 if(flg) printf("GOOD\n"); 51 else printf("BAD\n"); 52 continue; 53 } 54 return 0; 55 }