题目描述

满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中。由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉全席,而能够烹饪出经过专家认证的满汉全席,也是中国厨师最大的荣誉之一。 世界满汉全席协会是由能够料理满汉全席的专家厨师们所组成,而他们之间还细分为许多不同等级的厨师。为了招收新进的厨师进入世界满汉全席协会,将于近日举办满汉全席大赛,协会派遣许多会员当作评审员,为的就是要在參赛的厨师之中,找到满汉料理界的明日之星。 大会的规则如下:每位參赛的选手可以得到n 种材料,选手可以自由选择用满式或是汉式料理将材料当成菜肴。大会的评审制度是:共有m 位评审员分别把关。每一位评审员对于满汉全席有各自独特的見解,但基本见解是,要有兩样菜色作为满汉全席的标志。如某评审认为,如果没有汉式东坡肉跟满式的涮羊肉锅,就不能算是满汉全席。但避免过于有主見的审核,大会规定一个评审员除非是在认为必备的两样菜色都没有做出來的狀况下,才能淘汰一位选手,否则不能淘汰一位參赛者。换句话說,只要參赛者能在这兩种材料的做法中,其中一个符合评审的喜好即可通过该评审的审查。如材料有猪肉,羊肉和牛肉时,有四位评审员的喜好如下表: 评审一 评审二 评审三 评审四 满式牛肉 满式猪肉 汉式牛肉 汉式牛肉 汉式猪肉 满式羊肉 汉式猪肉 满式羊肉 如參赛者甲做出满式猪肉,满式羊肉和满式牛肉料理,他将无法满足评审三的要求,无法通过评审。而參赛者乙做出汉式猪肉,满式羊肉和满式牛肉料理,就可以满足所有评审的要求。 但大会后來发现,在这样的制度下如果材料选择跟派出的评审员没有特别安排好的话,所有的參赛者最多只能通过部分评审员的审查而不是全部,所以可能会发生没有人通过考核的情形。如有四个评审员喜好如下表时,则不論參赛者采取什么样的做法,都不可能通过所有评审的考核: 评审一 评审二 评审三 评审四 满式羊肉 满式猪肉 汉式羊肉 汉式羊肉 汉式猪肉 满式羊肉 汉式猪肉 满式猪肉 所以大会希望有人能写一个程序來判断,所选出的m 位评审,会不会发生 没有人能通过考核的窘境,以便协会组织合适的评审团。

输入

第一行包含一个数字 K,代表测试文件包含了K 组资料。每一组测试资料的第一行包含兩个数字n 跟m(n≤100,m≤1000),代表有n 种材料,m 位评审员。为方便起見,材料舍弃中文名称而给予编号,编号分别从1 到n。接下來的m 行,每行都代表对应的评审员所拥有的兩个喜好,每个喜好由一个英文字母跟一个数字代表,如m1 代表这个评审喜欢第1 个材料透过满式料理做出來的菜,而h2 代表这个评审员喜欢第2 个材料透过汉式料理做出來的菜。每个测试文件不会有超过50 组测试资料

输出

每笔测试资料输出一行,如果不会发生没有人能通过考核的窘境,输出GOOD;否则输出BAD(大写字母)。

样例输入

2
3 4
m3 h1
m1 m2
h1 h3
h3 m2
2 4
h1 m2
m2 m1
h1 h2
m1 h2

样例输出

GOOD
BAD
 

这道题有两种建图方式。

第一种是对于每种食材建四个点,分别代表选满、不选满、选汉、不选汉,然后将不选满连向选汉、不选汉连向选满。对于每个评委的条件连两条边,不选第一个就要选第二个,不选第二个就要选第一个。然后$tarjan$缩点,只要每种食材选满和选汉不在同一个强连通分量里就可行。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char s[10],t[10];
int dep[500];
int vis[500];
int st[500];
int top;
int tot;
int sum;
int now;
int head[500];
int to[4000];
int next[4000];
int bel[500];
int dfn;
int low[500];
int n,m;
int a,b,c,d;
int T;
void add(int x,int y)
{
next[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void tarjan(int x)
{
vis[x]=1;
st[++top]=x;
dep[x]=low[x]=++dfn;
for(int i=head[x];i;i=next[i])
{
if(!dep[to[i]])
{
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(vis[to[i]])
{
low[x]=min(low[x],dep[to[i]]);
}
}
if(dep[x]==low[x])
{
sum++;
do
{
now=st[top];
top--;
vis[now]=0;
bel[now]=sum;
}
while(now!=x);
}
}
int find(char *s)
{
int len=strlen(s);
int res=0;
for(int i=1;i<len;i++)
{
res=res*10+s[i]-'0';
}
return res;
}
void solve()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
add(n+i,2*n+i);
add(2*n+i,n+i);
add(3*n+i,i);
add(i,3*n+i);
}
for(int i=1;i<=m;i++)
{
scanf("%s%s",s,t);
a=(s[0]=='h');
b=find(s);
b=(a?2*n+b:b);
c=(t[0]=='h');
d=find(t);
d=(c?2*n+d:d);
add(d+n,b);
add(b+n,d);
}
for(int i=1;i<=4*n;i++)
{
if(!dep[i])
{
tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
if(bel[i]==bel[2*n+i])
{
printf("BAD\n");
return ;
}
}
printf("GOOD\n");
}
void init()
{
tot=dfn=top=sum=0;
memset(head,0,sizeof(head));
memset(bel,0,sizeof(bel));
memset(low,0,sizeof(low));
memset(dep,0,sizeof(dep));
memset(vis,0,sizeof(vis));
}
int main()
{
scanf("%d",&T);
while(T--)
{
init();
solve();
}
}

第二种建图方式直接对每种食材建两个点,分别表示选满和选汉。对于每个要求,例如$m1\ h2$,将$h1$连向$h2$,将$m2$连向$m1$。表示第一个不按要求选第二个就要按要求选,第二个不按要求选第一个就要按要求选。同样$tarjan$缩点之后判断每种食材的两个点是否在同一个强连通分量里即可。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char s[10],t[10];
int dep[500];
int vis[500];
int st[500];
int top;
int tot;
int sum;
int now;
int head[500];
int to[4000];
int next[4000];
int bel[500];
int dfn;
int low[500];
int n,m;
int a,b,c,d;
int T;
void add(int x,int y)
{
next[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void tarjan(int x)
{
vis[x]=1;
st[++top]=x;
dep[x]=low[x]=++dfn;
for(int i=head[x];i;i=next[i])
{
if(!dep[to[i]])
{
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(vis[to[i]])
{
low[x]=min(low[x],dep[to[i]]);
}
}
if(dep[x]==low[x])
{
sum++;
do
{
now=st[top];
top--;
vis[now]=0;
bel[now]=sum;
}
while(now!=x);
}
}
int find(char *s)
{
int len=strlen(s);
int res=0;
for(int i=1;i<len;i++)
{
res=res*10+s[i]-'0';
}
return res;
}
void solve()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%s%s",s,t);
a=(s[0]=='h');
b=find(s);
c=(t[0]=='h');
d=find(t);
add((a^1)*n+b,c*n+d);
add((c^1)*n+d,a*n+b);
}
for(int i=1;i<=2*n;i++)
{
if(!dep[i])
{
tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
if(bel[i]==bel[n+i])
{
printf("BAD\n");
return ;
}
}
printf("GOOD\n");
}
void init()
{
tot=dfn=top=sum=0;
memset(head,0,sizeof(head));
memset(bel,0,sizeof(bel));
memset(low,0,sizeof(low));
memset(dep,0,sizeof(dep));
memset(vis,0,sizeof(vis));
memset(next,0,sizeof(next));
memset(to,0,sizeof(to));
memset(st,0,sizeof(st));
}
int main()
{
scanf("%d",&T);
while(T--)
{
init();
solve();
}
}

BZOJ1823[JSOI2010]满汉全席——2-SAT+tarjan缩点的更多相关文章

  1. bzoj1823 [JSOI2010]满汉全席(2-SAT)

    1823: [JSOI2010]满汉全席 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1246  Solved: 598[Submit][Status ...

  2. Bzoj1823 [JSOI2010]满汉全席

    Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1640  Solved: 798 Description 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的 ...

  3. BZOJ1823 [JSOI2010]满汉全席 2-sat

    原文链接http://www.cnblogs.com/zhouzhendong/p/8125944.html 题目传送门 - BZOJ1823 题意概括 有n道菜,分别可以做成满式和汉式(每道菜只能做 ...

  4. 洛谷P4171 [JSOI2010] 满汉全席 [2-SAT,Tarjan]

    题目传送门 满汉全席 题目描述 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉 ...

  5. BZOJ1823 [JSOI2010]满汉全席 【2-sat】

    题目 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉全席,而能够烹饪出经过专家 ...

  6. bzoj 1823: [JSOI2010]满汉全席【2-SAT+tarjan】

    因为每种食材只有一份,所以两个评委的如果有要求同一种食材的两种做法就是不可行,用这个来建立2-SAT模型 然后跑tarjan判可行性即可 #include<iostream> #inclu ...

  7. [bzoj1823][JSOI2010]满汉全席——2-SAT

    题目大意 题目又丑又长我就不贴了,说一下大意,有n种菜,m个评委,每一个评委又有两种喜好,每种菜有满汉两种做法,只能选一种.判断是否存在一种方案使得所有评委至少喜欢一种菜品.输入包含多组数据. 题解 ...

  8. 【BZOJ1823】[JSOI2010]满汉全席(2-sat)

    [BZOJ1823][JSOI2010]满汉全席(2-sat) 题面 BZOJ 洛谷 题解 很明显的\(2-sat\)模板题,还不需要输出方案. 对于任意两组限制之间,检查有无同一种石材要用两种不同的 ...

  9. 【BZOJ1823】[JSOI2010]满汉全席 2-SAT

    [BZOJ1823][JSOI2010]满汉全席 Description 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只 ...

随机推荐

  1. ASP.Net Core 中使用Zookeeper搭建分布式环境中的配置中心系列一:使用Zookeeper.Net组件演示基本的操作

    前言:马上要过年了,祝大家新年快乐!在过年回家前分享一篇关于Zookeeper的文章,我们都知道现在微服务盛行,大数据.分布式系统中经常会使用到Zookeeper,它是微服务.分布式系统中必不可少的分 ...

  2. Django Rest framework基础使用之Request/Response

    1.Request restframework提供了一个Request对象(rest_framework.request.Request) Request对象继承了Django默认的HttpReque ...

  3. OSGI 环境搭建

    第一步,打开eclipse,新建一个plugin工程,如下图所示 第二步,输入工程的名字,并且在Target Platform中选择an OSGI framework中选中standard,如下图所示 ...

  4. Beta阶段团队成员贡献分分配规则

    Beta阶段团队成员贡献分分配规则 Alpha阶段贡献分分配有些负责,在这里进行一些修改: 对任务完成得分部分进行了简化 对发现bug的惩罚措施进行了修改 移除了优化得分,不鼓励修改他人代码 移除了帮 ...

  5. POJ 2406 Power Strings(KMP)

    Description Given two strings a and b we define a*b to be their concatenation. For example, if a = & ...

  6. Glad to see you! CodeForces - 810D (交互+二分)

    This is an interactive problem. In the output section below you will see the information about flush ...

  7. iOS--LaunchImage启动页设置及问题解决

    在Assets.xcassets中使用LaunchImage来设置启动图:   一.根据不同屏幕尺寸的需求设置不同的图片,可以参照下图: 1.点击Image.xcassets 进入图片管理,然后右击, ...

  8. Python3练习题 021:递归方法求阶乘

    利用递归方法求5!. 方法一 f = 1 for i in range(1,6):     f = f * i print(f)   方法二 import functools print(functo ...

  9. 使用css控制文字显示几行并且剩余部分隐藏(移动端和PC端同样适用)

    前言 有些需求需要我们控制一段文本最多显示几行,就像逛淘宝京东的评价楼层一样,有时可能还需要隐藏剩余部分,这样的需求我们怎么来解决呢? 解决办法 我们完全可以使用css来解决这一需求 1. 解决文本显 ...

  10. Ionic1.x项目中的Installing npm packages问题

    与npm远程源有关,可以通过cnpm来解决: 一.ionic start myApp blank --skip-npm(跳过Installing npm packages会产生的问题): 二.然后进入 ...