codeforces 1534C.Little Alawn‘s Puzzle

c o d e f o r c e s   1534 C . L i t t l e A l a w n ′ s P u z z l e \Huge{codeforces\ 1534C.Little Alawn's Puzzle} codeforces 1534C.LittleAlawnsPuzzle

文章目录

  • 思路
  • 标程

题目地址:Problem - 1534C - Codeforces

思路

题目给定两个长度为n的数组,数组元素均为1~n。题目要求进行若干次操作,使得每行数组中没有重复的数字。操作为:选中某一列并交换两元素。

  1. 这道题猛地一看没有什么思路,但是我们可以很容易知道:这两行数组的所有排列顺序最多有2^n中,因为每列都有两种可能
  2. 所以我们尝试用二叉树来表示(其中根节点为起始节点),这样我们从根节点出发到叶节点,若没有重复元素,则为一种排列方法
  3. 我们会发现这棵满二叉树中会有很多重复元素,因此我们考虑将其构造为有向图
  4. 这时我们会发现,该有向图中会出现若干自环每个自环可以让排列方式多一倍

例如:

1 2 3

2 3 1

这就是一个自环,将其变为每行都不重复只有两种可能。

因此我们需要构建出有向图,并查找自环个数需要注意自环中不能出现在其他自环中的元素(也就是已经查找过的元素)

标程

#include

using namespace std;

#define IOS ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
#define LL long long 
#define ULL unsigned long long 
#define PII pair<int, int>
#define lowbit(x) (x & -x)
#define Mid ((l + r) >> 1)
#define ALL(x) x.begin(), x.end()
#define endl '\n'
#define fi first 
#define se second

const int INF = 0x7fffffff;
const int mod = 1e9 + 7;
const int N = 2e5 + 10; 

void Solved() {
    int n; cin >> n;
    vector<vector<int>> a(n + 1, vector<int>(2)), f(n + 1);
    vector<bool> b(n + 1);

    function<void(int)> dfs = [&](int x) {
        b[x] = true;
        for(auto i : f[x]) if(!b[i]) dfs(i);
    };

    for(int i = 1; i <= n; i ++ ) cin >> a[i][0];
    for(int i = 1; i <= n; i ++ ) cin >> a[i][1];
    LL res = 1;
    for(int i = 1; i <= n; i ++ ) {
        f[a[i][0]].push_back(a[i][1]);
        f[a[i][1]].push_back(a[i][0]);
    }
    for(int i = 1; i <= n; i ++ ) {
        if(b[i]) continue;
        res = res * 2ll % mod;
        dfs(i);
    }
    cout << res << endl;
}

signed main(void) {
    IOS

    int ALL = 1; 
    cin >> ALL;
    while(ALL -- ) Solved();
    // cout << fixed;//强制以小数形式显示
    // cout << setprecision(n); //保留n位小数

    return 0;
}

你可能感兴趣的:(codeforces,codeforces,c++,算法)