• Codeforces 859E Desk Disorder 并查集找环,乘法原理


    题目链接:http://codeforces.com/contest/859/problem/E

    题意:有N个人。2N个座位。现在告诉你这N个人它们现在的座位。以及它们想去的座位。每个人可以去它们想去的座位或者就站在原地不动。新的座位和旧的座位,都不允许一个座位被两个人占据的情况。问你安排的方案数。

    解法:对于这N个点,N条边构成的图,我们应该对每个连通块独立计算答案,最后乘起来。如果n个点,n-1条边答案显然为n。如果n个点n条边,会出现一个环,且恰好只有一个环。如果是一个自环,那么答案是1,因为所有人都不能动。如果环的大小>=2的话,答案为2。

    维护环直接用并查集即可。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200010;
    const int mod = 1e9+7;
    namespace DSU{
        int fa[maxn], cycle[maxn], sz[maxn];
        void init(){
            for(int i=1; i<maxn; i++) fa[i] = i, sz[i] = 1, cycle[i] = 0;
        }
        int find_set(int x){
            if(x == fa[x]) return x;
            else return fa[x] = find_set(fa[x]);
        }
        void union_set(int x, int y){
            int fx = find_set(x);
            int fy = find_set(y);
            if(fx == fy){
                cycle[fx] = 1;
            }else{
                fa[fy] = fx;
                sz[fx] += sz[fy];
                cycle[fx] |= cycle[fy];
            }
        }
    }
    using namespace DSU;
    
    int main()
    {
        int n;
        cin >> n;
        init();
        long long ans = 1;
        for(int i=1; i<=n; i++){
            int x, y;
            cin >> x >> y;
            if(x == y){
                cycle[find_set(x)] = 2;
                continue;
            }
            union_set(x, y);
        }
        for(int i=1; i<=2*n; i++){
            if(find_set(i) == i){
                if(cycle[i] == 1) ans = ans*2%mod;
                else{
                    if(cycle[i] == 0) ans = ans * sz[i]%mod;
                }
            }
        }
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    Java链接 Oracle11g R2
    MARS3.6 Programming
    相关分析
    统计学中的P值与显著性的意义
    Java的输入/输出操作
    SQL Server数据类型一览表
    Fragstats:使用R软件读取frag78b.asc文件
    收藏一下大牛的数据挖掘学习经验
    数据库系统概论(第四版)习题解答
    ArcGIS中的坐标系统定义与投影转换
  • 原文地址:https://www.cnblogs.com/spfa/p/7563169.html
Copyright © 2020-2023  润新知