• Codeforces 776D.The Door Problem (dfs二分图判定 / 并查集)


    题目链接:

    http://codeforces.com/problemset/problem/776/D

    题意:

    n扇门,m个开关(n,m<=1e5),每个开关控制若干个门,反转开关门状态变化,每个门正好被两个开关控制,问是否有可能把所有门的状态置为1?

    思路:

    from: http://blog.csdn.net/jeremy1149/article/details/56839453

    方法一:二分图染色

    注意到一个门只被两个开关控制 若门初始为0 则控制它的两个开关状态相反,门初始为1则 要求控制的两个开关状态相同,才能可以把门置为1.

    以开关为顶点,(u,v)的边为被(u,v)控制的门的初始状态, dfs做二分图染色,判断每条边(每扇门)是否都能被满足

    方法二:并查集

    把每一个钥匙拆成两个点x,x+m,分别表示选不选这把钥匙。
    我们知道一扇门一定对应了两把钥匙。
    设一扇门对应的要是分别为u,v,link(x,y)表示点x向点y连边。
    如果这扇门要操作一次,那就是两把当中选一把:link(u,v+m),link(v,u+m)。这表示的是如果我选了拿第u把钥匙就不能拿第v把钥匙,如果我选了拿第v把钥匙就不能拿第u把钥匙
    如果这扇门不要操作,那就是两把当中选两把或者都不选:link(u+m,v+m),link(v,u)。这表示的是如果我选了拿第u把钥匙就一定要拿第v把钥匙,如果我不拿第v把钥匙就一定不能拿第u把钥匙
    这个是无向边啊,并查集维护一下关系即可。
    对于1...m中的每一把钥匙,如果x,x+m属于一个连通块就无解了,因为包含关系成环。

    代码:

    代码一:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define MS(a) memset(a,0,sizeof(a))
    #define MP make_pair
    #define PB push_back
    const int INF = 0x3f3f3f3f;
    const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    inline ll read(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //////////////////////////////////////////////////////////////////////////
    const int maxn = 1e5+10;
    
    int n,k,st[maxn],c[maxn],flag;
    vector<int> p[maxn];
    vector<pair<int,int> > g[maxn];
    
    void dfs(int u,int x){
        if(flag == false) return ;
        if(c[u] != -1){
            if(c[u] != x) flag=false;
            return ;
        }
        c[u] = x;
        for(int i=0; i<(int)g[u].size(); i++){
            int v = g[u][i].first, w = g[u][i].second;
            int y;
            if(w == 1) y = x;
            else y = x^1;
            dfs(v,y);
        }
    }
    
    int main(){
        cin >> n >> k;
        for(int i=1; i<=n; i++)
            st[i] = read();
        for(int i=1; i<=k; i++){
            int num = read();
            while(num--){
                int x = read();
                p[x].push_back(i);
            }
        }
        for(int i=1; i<=n; i++){
            int u = p[i][0], v = p[i][1];
            g[u].push_back(MP(v,st[i]));
            g[v].push_back(MP(u,st[i]));
        }
        flag = 1;
        memset(c,-1,sizeof(c));
        for(int i=1; i<=k; i++){
            if(c[i] == -1) dfs(i,0);
        }
    
        if(flag) puts("YES");
        else puts("NO");
        return 0;
    }

    代码二:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define MS(a) memset(a,0,sizeof(a))
    #define MP make_pair
    #define PB push_back
    const int INF = 0x3f3f3f3f;
    const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    inline ll read(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    //////////////////////////////////////////////////////////////////////////
    const int maxn = 2e5+10;
    
    int n,k,st[maxn],fa[maxn];
    vector<int> p[maxn];
    
    int find(int x){
        return fa[x]==x ? x : fa[x]=find(fa[x]);
    }
    
    void merge(int u,int v){
        int p1 = find(u), p2 = find(v);
        if(p1==p2) return ;
        fa[p1] = p2;
    }
    
    int main(){
        cin >> n >> k;
        for(int i=1; i<=n; i++)
            st[i] = read();
        for(int i=1; i<=k; i++){
            int num = read();
            for(int j=0; j<num; j++){
                int x = read();
                p[x].push_back(i);
            }
        }
        for(int i=1; i<=2*k; i++) fa[i]=i;
        for(int i=1; i<=n; i++){
            int u = p[i][0], v = p[i][1];
            if(st[i]){
                merge(u,v);
                merge(u+k,v+k);
            }else{
                merge(u,v+k);
                merge(u+k,v);
            }
        }
        for(int i=1; i<=k; i++){
            if(find(i) == find(i+k)){
                puts("NO");
                return 0;
            }
        }
        puts("YES");
    
        return 0;
    }
  • 相关阅读:
    数据分析项目补充:医院药品销售数据分析
    会计实务会计分录——资产之流动资产篇
    HTTP请求过程和状态响应码
    网络爬虫深究-初识HTTP和https常识
    数字分析之一元线性回归及多元线性回归
    Navicat15激活(仅供学习使用,严禁任何商业用途)
    pandas补充(其二)与matplotlib补充
    pandas模块补充
    阿里云ecs服务器公网ip除了能telnet通22端口,其他如tomcat的8080端口telnet不通,原来需要添加安全组规则
    maven依赖里redis的依赖spring-boot-starter-data-redis和spring-boot-starter-redis有什么区别?
  • 原文地址:https://www.cnblogs.com/yxg123123/p/7245681.html
Copyright © 2020-2023  润新知