题目描述

满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中。由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉全席,而能够烹饪出经过专家认证的满汉全席,也是中国厨师最大的荣誉之一。 世界满汉全席协会是由能够料理满汉全席的专家厨师们所组成,而他们之间还细分为许多不同等级的厨师。为了招收新进的厨师进入世界满汉全席协会,将于近日举办满汉全席大赛,协会派遣许多会员当作评审员,为的就是要在參赛的厨师之中,找到满汉料理界的明日之星。 大会的规则如下:每位參赛的选手可以得到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. git 分支管理规范

    保证master分支永远处于可部署的状态.禁止自接提交代码到master分支 开发分支基于master分支创建,命名规范如下: 如果是功能需求,分支命名为feature/xxx,xxx要具有描述性 如 ...

  2. Charles 抓包工具安装和采坑记录

    Charles 抓包工具安装和采坑记录 网络抓包是解决网络问题的第一步,也是网络分析的基础.网络出现问题,第一步肯定是通过抓包工具进行路径分析,看哪一步出现异常.做网络爬虫,第一步就是通过抓包工具对目 ...

  3. P2P平台介绍

    https://www.ludou.org/tutengdai.html https://www.tutengdai.com/register?invite_code=9991300

  4. Linux 命令(二)

    man help:线上查询及帮助命令 命令  --help:简单帮助 help  cd:查看一些Linux命令行的一些内置命令 文件和目操作命令(19个) ls  cd  cp  find  mkdi ...

  5. Macaca初体验-Android端(Python)

    前言: Macaca 是一套面向用户端软件的测试解决方案,提供了自动化驱动,周边工具,集成方案.由阿里巴巴公司开源:http://macacajs.github.io/macaca/ 特点: 同时支持 ...

  6. H5 video标签的第二种格式

    36-video标签的第二种格式 2.第二种格式存在的意义: 由于视频数据非常非常的重要, 所以五大浏览器厂商都不愿意支持别人的视频格式, 所以导致了没有一种视频格式是所有浏览器都支持的 这个时候W3 ...

  7. mysql 中Varchar 与char的区别

    一.字符与字节与编码关系 ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间.一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制.最 ...

  8. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.bw.mapper.BillMapper.getBillList at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:225

    这个错误是没有找到映射文件 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.b ...

  9. 什么是arp协议?

    转自:https://blog.csdn.net/tigerjibo/article/details/7351992 ARP (Address Resolution Protocol) 是个地址解析协 ...

  10. Windows 机器上面同时安装mysql5.6 和 mysql5.7 的方法

    1. 自己遇到的两个坑: . mysql 登录的时候 需要使用-P 来指定端口号 不然默认走 呢 . mysql 5.6 和 mysql 5.7 更改用户密码的命令不一样.. 我这边浪费了很长时间: ...