zoukankan      html  css  js  c++  java
  • 题解 洛谷 P4171 【[JSOI2010]满汉全席】

    考虑(2-SAT)

    将汉式看作(0)状态,满式看做(1)状态,将每个材料拆成(01)两个状态。

    (a)(b)连有向边表示的意义为选了(a)后必须选(b)

    那么每次连边的方式如下:

    (add(x_{a oplus 1},y_b),add(y_{b oplus 1},x_a))(x_a)(y_b)为评审员的要求,(x)(y)表示材料,(a)(b)表示状态)

    意义为若没有满足评审员的其中一个要求,则另一个要求必须满足。

    连边后缩点,若发现(x_a)(x_{a oplus 1})在同一强连通分量中,则无解。

    其他的一些实现的处理,就看代码吧。

    (code:)

    #include<bits/stdc++.h>
    #define maxn 4000010
    using namespace std;
    template<typename T> inline void read(T &x)
    {
    	x=0;char c=getchar();bool flag=false;
    	while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	if(flag)x=-x;
    }
    int t,n,m;
    char str[5];
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to)
    {
        e[++edge_cnt]=(edge){to,head[from]};
        head[from]=edge_cnt;
    }
    int dfn_cnt,co_cnt,top;
    int dfn[maxn],low[maxn],co[maxn],st[maxn];
    bool vis[maxn];
    void tarjan(int x)
    {
        dfn[x]=low[x]=++dfn_cnt;
        st[++top]=x;
        vis[x]=true;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(!dfn[y])
            {
                tarjan(y);;
                low[x]=min(low[x],low[y]);
            }
            else if(vis[y])
                low[x]=min(low[x],dfn[y]);
        }
        if(low[x]==dfn[x])
        {
            co_cnt++;
            int now;
            do
            {
                now=st[top--];
                vis[now]=false;
                co[now]=co_cnt;
            }while(now!=x);
        }
    }
    bool check()
    {
        for(int i=1;i<=2*n;++i)
            if(!dfn[i])
                tarjan(i);
        for(int i=1;i<=n;++i)
            if(co[i]==co[i+n])
                return false;
        return true;
    }
    void clear()
    {
        top=dfn_cnt=co_cnt=edge_cnt=0;
        memset(co,0,sizeof(co));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(vis,0,sizeof(vis));
        memset(head,0,sizeof(head));
    }
    int main()
    {
    	read(t);
        while(t--)
        {
            clear();
            read(n),read(m);
            while(m--)
            {
                int x,y,a,b,len;
                scanf("%s",str);
                if(str[0]=='h') a=0;
                else a=1;
                x=0,len=strlen(str);
                for(int i=1;i<len;++i) x=x*10+str[i]-'0';
                scanf("%s",str);
                if(str[0]=='h') b=0;
                else b=1;
                y=0,len=strlen(str);
                for(int i=1;i<len;++i) y=y*10+str[i]-'0';
                add(x+(a^1)*n,y+b*n),add(y+(b^1)*n,x+a*n);
            }
            if(check()) puts("GOOD");
            else puts("BAD");
        }
    	return 0;
    }
    
  • 相关阅读:
    装饰模式
    普元EOS生成WebService时使用自定义实体映射属性
    Mysql字符串查询注意事项(空格敏感及部分字段大小写敏感问题)
    java数组转换为集合-Arrays.asList使用
    Java报异常时getMessage()方法返回null
    118. Pascal's Triangle
    13. Roman to Integer
    9. Palindrome Number
    8. String to Integer (atoi)
    7. Reverse Integer
  • 原文地址:https://www.cnblogs.com/lhm-/p/12229832.html
Copyright © 2011-2022 走看看