zoukankan      html  css  js  c++  java
  • 洛谷P4171

    题目很长,废话很多,但是很板

    Description

    给出 (n) 个数,(m) 个条件

    每个数有两种类型,只能选择其中一种类型

    每组条件包含两个,每个要求一种类型的数字

    问这 (n) 个数能不能符合所有的条件

    Solution

    问所有数字能否满足所有的条件,显然是适定性问题

    首先要明确一点,每组的条件至少满足一个,也就是说可以全部满足

    但要想让答案最优,选择满足其中一个就好,因为这样能用更少的数字满足更多的条件

    那每次两个条件满足其一,显然选择 2-SAT 求解

    考虑如何建边

    由于题目中有 每种材料只能做一种菜式 的限制,所以我们对于每组条件的每一个,向另一种条件的对立事件建边

    假设 (a,b) 处于同一组条件,(A,B) 分别是他们的另一种类型

    那我们建有向边 ((a,B))((b,A)),表示选择 (a) 必须选择 (B),选择 (b) 必须选择 (A),同时满足上面的最优性说明

    之后跑强连通分量,判断在同一个 SCC 内,是否有两个条件处于同一组,无则成立,有则不成立

    Code

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #define maxn 100100
    #define rr register 
    #define INF 0x3f3f3f3f
    //#define int long long
    #define debug cout<<"lkp ak ioi"<<endl
    
    using namespace std;
    
    string s1,s2;
    bool vis[maxn],flag;
    int k,n,m,top,tot,t,cnt; 
    int low[maxn],head[maxn],dfn[maxn],num[maxn],zhan[maxn];
    struct edge{int fr,to,nxt;}e[maxn<<1];
    
    inline int read(){
        int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
        return s*w;
    }
    
    void add(int fr,int to){
        e[++tot].to=to;e[tot].fr=fr;
        e[tot].nxt=head[fr];head[fr]=tot;
    }
    
    int Turn(string s){
        int ans=0;
        for(int i=1;i<s.length();i++)
    	ans*=10,ans+=s[i]-'0';	
        if(s[0]=='h') return ans;
        return ans+n;
    }
    
    int No(string s){
        int ans=0;
        for(int i=1;i<s.length();i++)
            ans*=10,ans+=s[i]-'0';	
        if(s[0]=='h') return ans+n;
        return ans;
    }
    
    void clear(){
        tot=top=t=cnt=flag=0;
        memset(dfn,0,sizeof dfn);
        memset(low,0,sizeof low);
        memset(num,0,sizeof num);
        memset(vis,0,sizeof vis);
        memset(head,0,sizeof head);
    }
    
    void tarjan(int u){
        dfn[u]=low[u]=++cnt;
        vis[u]=1;zhan[++top]=u;
        for(int i=head[u];i;i=e[i].nxt){
            int to=e[i].to;
            if(!dfn[to]) tarjan(to),low[u]=min(low[u],low[to]);
            else if(vis[to]) low[u]=min(low[u],dfn[to]);
        }
        if(dfn[u]==low[u]){
            int pre=zhan[top--];
            num[pre]=++t;vis[pre]=0;
            while(pre!=u){
                pre=zhan[top--];
                num[pre]=t;vis[pre]=0;
            }
        }
    }
    
    int main(){
        k=read();
        while(k--){
            clear();n=read();m=read();
            for(int i=1;i<=m;i++){
                cin>>s1>>s2;
                add(Turn(s1),No(s2));
                add(Turn(s2),No(s1));
            }
            for(int i=1;i<=n*2;i++)if(!dfn[i])tarjan(i); 
            for(int i=1;i<=n;i++)if(num[i]==num[i+n]){printf("BAD
    ");flag=1;break;}
            if(!flag) printf("GOOD
    ");
        }
        return 0;
    } 
    
  • 相关阅读:
    Spring Boot (20) 拦截器
    Spring Boot (19) servlet、filter、listener
    Spring Boot (18) @Async异步
    Spring Boot (17) 发送邮件
    Spring Boot (16) logback和access日志
    Spring Boot (15) pom.xml设置
    Spring Boot (14) 数据源配置原理
    Spring Boot (13) druid监控
    Spring boot (12) tomcat jdbc连接池
    Spring Boot (11) mybatis 关联映射
  • 原文地址:https://www.cnblogs.com/KnightL/p/14365855.html
Copyright © 2011-2022 走看看