题解 P4171 【[JSOI2010]满汉全席】

满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在数量繁多的菜色之中。由于菜色众多而繁杂,只有极少数博学多闻技艺高超的厨师能够做出满汉全席,而能够烹饪出经过专家认证的满汉全席,也是中国厨师最大的荣誉之一。世界满汉全席协会是由能够料理满汉全席的专家厨师们所组成,而他们之间还细分为许多不同等级的厨师。

为了招收新进的厨师进入世界满汉全席协会,将于近日举办满汉全席大赛,协会派遣许多会员当作评审员,为的就是要在参赛的厨师之中,找到满汉界的明日之星。

大会的规则如下:每位参赛的选手可以得到 nn 种材料,选手可以自由选择用满式或是汉式料理将材料当成菜肴。

大会的评审制度是:共有 mm 位评审员分别把关。每一位评审员对于满汉全席有各自独特的见解,但基本见解是,要有两样菜色作为满汉全席的标志。如某评审认为,如果没有汉式东坡肉跟满式的涮羊肉锅,就不能算是满汉全席。但避免过于有主见的审核,大会规定一个评审员除非是在认为必备的两样菜色都没有做出来的状况下,才能淘汰一位选手,否则能淘汰一位参赛者。

换句话说,只要参赛者能在这两种材料的做法中,其中一个符合评审的喜好即可通过该评审的审查。如材料有猪肉,羊肉和牛肉时,有四位评审员的喜好如下表:

评审一 评审二 评审三 评审四 
满式牛肉 满式猪肉 汉式牛肉 汉式牛肉 
汉式猪肉 满式羊肉 汉式猪肉 满式羊肉 

如参赛者甲做出满式猪肉,满式羊肉和满式牛肉料理,他将无法满足评审三的要求,无法通过评审。而參赛者乙做出汉式猪肉,满式羊肉和满式牛肉料理,就可以满足所有评审的要求。

但大会后来发现,在这样的制度下如果材料选择跟派出的评审员没有特别安排好的话,所有的参赛者最多只能通过部分评审员的审查而不是全部,所以可能会发生没有人通过考核的情形。

如有四个评审员喜好如下表时,则不论参赛者采取什么样的做法,都不可能通过所有评审的考核:

评审一 评审二 评审三 评审四 
满式羊肉 满式猪肉 汉式羊肉 汉式羊肉 
汉式猪肉 满式羊肉 汉式猪肉 满式猪肉 

所以大会希望有人能写一个程序来判断,所选出的 mm 位评审,会不会发生没有人能通过考核的窘>境,以便协会组织合适的评审团。

前置知识:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &FF,T &X){
	FF=0;char CH=getchar();
	for(;!isdigit(CH);CH=getchar())/*cout<<CH<<" ",*/X=CH=='m'?1:X,X=CH=='h'?0:X;//,cout<<X<<endl;
	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
	// cout<<X<<" "<<FF<<endl;
}
template<typename T>inline void read1(T &FF){
	T RR=1;FF=0;char CH=getchar();
	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
	FF*=RR;
}
const int MAXN=3e6+10;
int n,m,a,b,a1,b1,dfn[MAXN],low[MAXN],tot,s[MAXN],sp,sccnum[MAXN],scccnt,T;
vector<int>E[MAXN];
void tarjan(int u){
	s[sp++]=u;
	dfn[u]=low[u]=++tot;
	for(auto v:E[u])
		if(!dfn[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}else if(!sccnum[v]){
			low[u]=min(low[u],dfn[v]);
		}
	if(dfn[u]==low[u]){
		scccnt++;
		do{
			sccnum[s[--sp]]=scccnt;
		}while(s[sp]!=u);
	}
}
void solve(){
	sp=0;tot=0;
	read1(n);read1(m);
	// memset(sccnum,0,sizeof())
	for(int i=1;i<=(n<<1);i++){
		E[i].clear();
		dfn[i]=0;
		sccnum[i]=0;
		low[i]=0;
	}
	for(int i=1;i<=m;i++){
		read(a,a1);read(b,b1);
        E[a+(a1^1)*n].push_back(b+b1*n);
    	E[b+(b1^1)*n].push_back(a+a1*n);
	}
	for(int i=1;i<=(n<<1);i++)
		if(!dfn[i])tarjan(i);
	for(int i=1;i<=(n<<1);i++)
		if(sccnum[i]==sccnum[i+n])return (void)puts("BAD");
	puts("GOOD");
}
int main(){
	read1(T);
	while(T--)solve();
	return 0;
}
/*
3 1
1 1 3 0
*/
原文地址:https://www.cnblogs.com/zhaohaikun/p/12816932.html