[JSOI 2010] 满汉全席

本文深入解析了2-SAT算法的原理及其在解决特定逻辑问题中的应用。通过一个具体的编程实例,详细展示了如何使用2-SAT算法来判断一组命题逻辑公式是否具有一致的解决方案。代码中包含了深度优先搜索(DFS)和Tarjan算法实现强连通分量(SCC)的计算,以此来确定是否存在冲突的命题组合。

[题目链接]

          https://www.lydsy.com/JudgeOnline/problem.php?id=1823

[算法]

         2-SAT

[代码]

#include<bits/stdc++.h>
using namespace std;
#define MAXN 110
#define MAXM 1010

struct edge
{
        int to,nxt;
} e[MAXM << 1];

int timer,cnt,top,tot;
int dfn[MAXN << 1],low[MAXN << 1],belong[MAXN << 1],s[MAXN << 1],head[MAXN << 1];
bool instack[MAXN];

template <typename T> inline void read(T &x)
{
        int f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
}
inline void addedge(int u,int v)
{
        tot++;
        e[tot] = (edge){v,head[u]};
        head[u] = tot; 
}
inline void tarjan(int u)
{
        low[u] = dfn[u] = ++timer;
        instack[u] = true;
        s[++top] = u;
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (!dfn[v])
                {
                        tarjan(v);
                        low[u] = min(low[u],low[v]);
                } else if (instack[v]) low[u] = min(low[u],dfn[v]);
        }
        if (low[u] == dfn[u])
        {
                cnt++;
                while (s[top + 1] != u)
                {
                        instack[s[top]] = false;
                        belong[s[top]] = cnt;
                        top--;
                }
        }
}
int main() 
{
        
        int T;
        read(T);
        while (T--)        
        {
                int n,m;
                read(n); read(m);
                tot = 0;
                for (int i = 1; i <= 2 * n; i++) head[i] = 0;
                for (int i = 1; i <= m; i++)
                {
                        char a[20] , b[20];
                        scanf("%s%s",a + 1,b + 1);
                        int t1 = 0 , t2 = 0;
                        for (int j = 2; j <= strlen(a + 1); j++) t1 = t1 * 10 + a[j] - '0';
                        for (int j = 2; j <= strlen(b + 1); j++) t2 = t2 * 10 + b[j] - '0';
                        if (a[1] == 'm') addedge(t1 + n,t2 + (b[1] == 'h') * n);
                        else addedge(t1,t2 + (b[1] == 'h') * n);
                        if (b[1] == 'm') addedge(t2 + n,t1 + (a[1] == 'h') * n);
                        else addedge(t2,t1 + (a[1] == 'h') * n);
                } 
                timer = cnt = 0;
                for (int i = 1; i <= 2 * n; i++) low[i] = dfn[i] = 0;
                for (int i = 1; i <= 2 * n; i++)
                {
                        if (!dfn[i])
                                tarjan(i);
                }
                bool ans = true;
                for (int i = 1; i <= n; i++)
                {
                      if (belong[i] == belong[i + n]) 
                      {
                              ans = false;
                              break;
                        }
                }
                if (ans) printf("GOOD\n");
                else printf("BAD\n");
        }
        
        return 0;
    
}

 

转载于:https://www.cnblogs.com/evenbao/p/9508025.html

解释样例,按照以下格式建图 c++ 例如,要建 -a -> b的边,就用 fa b Problem H: [JSOI2010]满汉全席 Time Limit: 1 Sec Memory Limit: 128 MB Description 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在数量繁多的菜色之中。由于菜色众多而繁杂,只有极少数博学多闻技艺高超的厨师能够做出满汉全席,而能够烹饪出经过专家认证的满汉全席,也是中国厨师最大的荣誉之一。 世界满汉全席协会是由能够料理满汉全席的专家厨师们所组成,而他们之间还细分为许多不同等级的厨师。为了招收新进的厨师进入世界满汉全席协会,将于近日举办满汉全席大赛,协会派遣许多会员当作评审员,为的就是要在参赛的厨师之中,找到满汉料理界的明日之星。 大会的规则如下:每位参赛的选手可以得到n种材料,选手可以自由选择用满式或是汉式料理将材料当成菜肴。 大会的评审制度是:共有m位评审员分别把关。每一位评审员对于满汉全席有各自独特的见解,但基本见解是,要有两样菜色作为满汉全席的标志。如某评审认为,如果没有汉式东坡肉跟满式的涮羊肉锅,就不能算是满汉全席。但避免过于有主见的审核,大会规定一个评审员除非是在认为必备的两样菜色都没有做出来的情况下,才能淘汰一位选手,否则不能淘汰一位参赛者。换句话说,只要参赛者能在这两种材料的做法中,其中一个符合评审的喜好即可通过该评审的审查。如材料有猪肉,羊肉和牛肉时,有四位评审员的喜好如下表: 评审一 评审二 评审三 评审四 满式牛肉 满式猪肉 汉式牛肉 汉式牛肉 汉式猪肉 满式羊肉 汉式猪肉 满式羊肉 如参赛者甲做出满式猪肉,满式羊肉和满式牛肉料理,他将无法满足评审三的要求,无法通过评审。而参赛者乙做出汉式猪肉,满式羊肉和满式牛肉料理,就可以满足所有评审的要求。 但大会后来发现,在这样的制度下如果材料选择跟派出的评审员没有特别安排好的话,所有的参赛者最多只能通过部分评审员的审查而不是全部,所以可能会发生没有人通过考核的情形。 如有四个评审员喜好如下表时,则不论参赛者采取什么样的做法,都不可能通过所有评审的考核: 评审一 评审二 评审三 评审四 满式羊肉 满式猪肉 汉式羊肉 汉式羊肉 汉式猪肉 满式羊肉 汉式猪肉 满式猪肉 所以大会希望有人能写一个程序来判断,所选出的m位评审,会不会发生没有人能通过考核的窘境,以便协会组织合适的评审团。 Input 第一行包含一个数字 K,代表测试文件包含了K 组资料。 每一组测试资料的第一行包含两个数字n 跟m(n≤100,m≤1000),代表有n 种材料,m 位评审员。为方便起见,材料舍弃中文名称而给予编号,编号分别从1 到n。 接下来的m 行,每行都代表对应的评审员所拥有的两个喜好,每个喜好由一个英文字母跟一个数字代表,如m1 代表这个评审喜欢第1 个材料透过满式料理做出来的菜,而h2 代表这个评审员喜欢第2 个材料透过汉式料理做出来的菜。 每个测试文件不会有超过50 组测试资料 Output 每笔测试资料输出一行,如果不会发生没有人能通过考核的窘境,输出GOOD;否则输出BAD(大写字母)。 Sample Input 2 3 4 m3 h1 m1 m2 h1 h3 h3 m2 2 4 h1 m2 m2 m1 h1 h2 m1 h2 Sample Output GOOD BAD
12-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值