题目描述

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

    本文将通过实现一个简易的线程池理解线程池的原理,以及介绍JDK中自带的线程池ThreadPoolExecutor和Executor框架. 1.无限制线程的缺陷 多线程的软件设计方法确实可以最大限度地发 ...

  2. docker创建nginx+php-fpm+mysql环境(一分钟搭建lnmp)

    下载镜像 docker pull bitnami/php-fpm #下载php-fpm镜像 docker pull nginx #下载nginx镜像docker pull mysql:5.5.59 # ...

  3. Randomized Online PCA Algorithms with Regret Bounds that are Logarithmic in the Dimension

    目录 Setup of Batch PCA and Online PCA Hedge Algorithm 改进算法 用于矩阵 \(rounding()\) 前俩次,都用到了\(rounding()\) ...

  4. PS电商产品banner设计

  5. HTTPS建立连接的过程

    HTTP建立连接的过程点击:HTTP三次握手.一次HTTP请求都发生了什么 一.HTTPS   HTTP是超文本传输协议.HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私 ...

  6. MySQL中关于数据类型指定宽度之后的情况

    概述 MySQL有很多种数据类型,最常用的就是int,char,varchar,这些类型在创建表的时候都可以指定该字段的宽度,方法是在类型后面加一个括号,括号中写宽度就可以了. 但是,在指定宽度之后, ...

  7. 敏捷与CMM的恩怨

    模式不同,一种是灵活,一种是严肃.

  8. Centos6.x升级内核方法支持Docker

    Centos6升级内核方法_百度经验https://jingyan.baidu.com/article/7e4409531bda252fc1e2ef4c.html

  9. PHP中对象的深拷贝与浅拷贝

    先说一下深拷贝和浅拷贝通俗理解 深拷贝:赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个 浅拷贝:赋值时,引用赋值,相当于取了一个别名.对其中一个修改,会影响另一个 PHP中, = ...

  10. mysql5.7以上安装

    下载:https://dev.mysql.com/downloads/mysql/ 1.在解压的mysql下(bin目录统计),创建my.ini 文件,内容日下(路径根据自己的目录修改) [mysql ...