• 【34.40%】【codeforces 711D】Directed Roads


    time limit per test2 seconds
    memory limit per test256 megabytes
    inputstandard input
    outputstandard output
    ZS the Coder and Chris the Baboon has explored Udayland for quite some time. They realize that it consists of n towns numbered from 1 to n.

    There are n directed roads in the Udayland. i-th of them goes from town i to some other town ai (ai ≠ i). ZS the Coder can flip the direction of any road in Udayland, i.e. if it goes from town A to town B before the flip, it will go from town B to town A after.

    ZS the Coder considers the roads in the Udayland confusing, if there is a sequence of distinct towns A1, A2, …, Ak (k > 1) such that for every 1 ≤ i < k there is a road from town Ai to town Ai + 1 and another road from town Ak to town A1. In other words, the roads are confusing if some of them form a directed cycle of some towns.

    Now ZS the Coder wonders how many sets of roads (there are 2n variants) in initial configuration can he choose to flip such that after flipping each road in the set exactly once, the resulting network will not be confusing.

    Note that it is allowed that after the flipping there are more than one directed road from some town and possibly some towns with no roads leading out of it, or multiple roads between any pair of cities.

    Input
    The first line of the input contains single integer n (2 ≤ n ≤ 2·105) — the number of towns in Udayland.

    The next line contains n integers a1, a2, …, an (1 ≤ ai ≤ n, ai ≠ i), ai denotes a road going from town i to town ai.

    Output
    Print a single integer — the number of ways to flip some set of the roads so that the resulting whole set of all roads is not confusing. Since this number may be too large, print the answer modulo 109 + 7.

    Examples
    input
    3
    2 3 1
    output
    6
    input
    4
    2 1 1 1
    output
    8
    input
    5
    2 4 2 5 3
    output
    28
    Note
    Consider the first sample case. There are 3 towns and 3 roads. The towns are numbered from 1 to 3 and the roads are , , initially. Number the roads 1 to 3 in this order.

    The sets of roads that ZS the Coder can flip (to make them not confusing) are {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}. Note that the empty set is invalid because if no roads are flipped, then towns 1, 2, 3 is form a directed cycle, so it is confusing. Similarly, flipping all roads is confusing too. Thus, there are a total of 6 possible sets ZS the Coder can flip.

    The sample image shows all possible ways of orienting the roads from the first sample such that the network is not confusing.
    这里写图片描述

    【题解】

    这题有特殊性,每个点都只有一个出度。只有n条边。
    那就保证了一张图里面不会有复杂的环
    最多只有这样
    这里写图片描述
    也就是说每个子图里面最坏的情况就是一个环带着几条链。
    先考虑最简单的情况。即一条链。
    那么设链的边数为x,则有2^x种翻转的方法(每条边都可以选择翻转或不翻转);最后都没有环。
    那对于一个环里面的x条边呢?
    环一定是简单的换。即1->2->3->1类似这样的
    可以看到每条边如果翻转一下都可以破坏这个环。
    那么x条边总共有2^x种方法破坏它。
    而全部都翻转或者全部都不翻转所形成依然是个环。所以要减去2
    即(2^X)-2
    然后每张子图都是一个环带几条链。
    我们先处理出所有子图的链上的边的个数cnt;
    (链的边的个数可用拓扑排序求得);
    ans = 2^cnt;
    然后对于第i个子图上的环的边的个数Xi
    根据乘法原理
    ans = ans*∏((2^xi)-2);
    (∏代表连乘);
    在做的过程中取余就好

    #include <cstdio>
    #include <queue>
    #include <iostream>
    
    using namespace std;
    
    const int MAXN = 3e5;
    const int MOD = 1e9 + 7;
    
    int n;
    long long re[MAXN];
    queue <int> dl;
    int to[MAXN],du[MAXN];
    long long ans;
    bool vis[MAXN];
    
    void input(int &r)
    {
        r = 0;
        char t = getchar();
        while (!isdigit(t)) t = getchar();
        while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    }
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        input(n);
        re[0] = 1;
        for (int i = 1; i <= n; i++)
            re[i] = (re[i - 1] * 2) % MOD;
        for (int i = 1; i <= n; i++)
        {
            input(to[i]);
            du[to[i]]++;
        }
        int cnt = 0;
        for (int i = 1;i <= n;i++)
            if (!du[i])
            {
                dl.push(i);
                cnt++;
            }
        while (!dl.empty())
        {
            int x = dl.front();
            vis[x] = true;
            dl.pop();
            du[to[x]]--;
            if (du[to[x]] == 0)
            {
                dl.push(to[x]);
                cnt++;
            }
        }
        ans = re[cnt];//cnt是所有子图上链的边的个数
        for (int i = 1; i <= n; i++)
            if (!vis[i])//每个子图的环的个数要单独算
            {
                int x = i, now = 0;
                while (!vis[x])
                {
                    now++;
                    vis[x] = true;
                    x = to[x];
                }
                ans = (ans*(re[now] - 2 + MOD)) % MOD;
            }
        printf("%I64d
    ", ans);
        return 0;
    }
  • 相关阅读:
    2018-10-20-WPF-通过位处理合并图片
    2019-2-11-WPF-获取应用的所有窗口
    2019-2-11-WPF-获取应用的所有窗口
    2018-8-10-WPF-如何在绑定失败异常
    2018-8-10-WPF-如何在绑定失败异常
    类和对象
    类和对象
    什么是可串行化MVCC
    LeetCode-环形链表|+环形链表||
    用js仿探探拖拽卡片的效果、飞卡片的效果,感觉挺酷,最后有美女看哦!
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632164.html
Copyright © 2020-2023  润新知