2017.12.23 浙江工大 迎新赛

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017.12.23 浙江工大 迎新赛相关的知识,希望对你有一定的参考价值。

A .

题目描述

        小杰是学院中公认的计算机大神,有一天小杰受邀去机房帮忙接网线,他三下五除二地就帮忙完成了。可是善于思考地他仍意有未尽,他觉得这次的线路有许多奇妙的性质,故来请教你。
        机房有n台不同的主机(编号为0,1,2,?,n?1),共连有n条网线,每台主机恰连着两条网线,通向其他的主机。相互之间有网线相连的主机可以通信,主机可以转发其他主机的信息,换句话说,如果主机A和主机C可以通信,主机B和主机C可以通信,那么主机A和主机B可以通信。现在想在一些主机间添加一些网线,使得任意一个主机故障时,其他的主机之间仍能互相通信(注:在一个主机故障时,所有与该主机直接相连的线路将无法使用)。那么问题来了,在添加的网线最少时,请问有多少种连线的方案,由于连线方案可能非常多,请将方案数对1000,000,007取模。

输入描述:

第一行表示主机数n。
接下来有n行,第i(i=0,1,2,?,n?1)行有两个数a,b,表示主机i和主机a,主机i和主机b各有网线相连。
输入有多组数据,n=0时,表示输入结束,请不要有对该组数据任何输出。

输出描述:

每组数据输出一行,表示方案数对1000,000,007取模的结果。(行末不要有多余的空白字符)
示例1

输入

5
2 3
4 4
0 3
0 2
1 1
12
11 11
10 10
9 9
8 8
7 7
6 6
5 5
4 4
3 3
2 2
1 1
0 0
2
1 1
0 0
0

输出

6
3
0

备注:

2≤n≤3×105,
不超过10组数据 n≥2×105,
不超过20组数据 n≥104,
总数据组数不超过200
 
题目分析 : 其实题目就是让找有多少个联通的图,并且找到每个独立的图中有多少个点,要将所有的图都连通,且保证当只有一个主机坏的时候,其他主机仍保持连通,则可以从每个独立的块中选择两个点出来去进行相连,C(n, 2),每面对两个独立的图,则会在乘以 2 ,因为可以交换点的顺序么,然后再是所有独立连通图的排列顺序,有(n-1)! 种 。
 
补充两个很坑的点 !!!
并查集的路径压缩部分,以前学的版本他路径压缩是不完全的 !! , 必须得最后在遍历一遍补充一些点进行路径压缩 !!!
第二点就是 long long 的地方, 拼经验的地方, long long  ans 要先给大数值 !!! 虽然还不知道为什么 !!
 
#define ll long long
const int eps = 3e5+5;
const ll mod = 1000000007;
const double pi = acos(-1.0);
const int inf = 1<<29;
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a


int f[eps];
int num[eps];
int n;
ll jc[eps];
ll fang[eps];

int fid(int x){
    //return x==f[x]?x:fid(f[x]);
    int r = x;
    while(r != f[r]){
        r = f[r];
    }
    
    int p = x;
    while(p != r){
        int t = f[p];
        f[p] = r;
        p = t;
    }
    return r;
}

void fun(){
    fang[0] = 1;
    jc[0] = 1;
    for(ll i = 1; i <= 300000; i++){
        jc[i] = jc[i-1]*i;
        fang[i] = fang[i-1]*2;
        jc[i] %= mod;
        fang[i] %= mod;
    }
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);

    int a, b;
    fun();
    map<int, int>mp;
    
    while(~scanf("%d", &n) && n){
        for(ll i = 0; i <= 300000; i++) f[i] = i;
        for(int i = 0; i < n; i++){
            scanf("%d%d", &a, &b);
            int fi = fid(i);
            int fa = fid(a);
            if (fi != fa){
                f[fa] = fi;
            }
            int fb = fid(b);
            if (fi != fb) f[fb] = fi;
        }
         
        mp.clear();
        for(int i = 0; i < n; i++){
            f[i] = fid(i);   // 补充路径压缩 !!
            mp[f[i]]++;
        }
         
        int cnt = mp.size();
        map<int, int>::iterator it;
        
        ll ans = jc[cnt-1]*fang[cnt-1]%mod;
        //ll ans = 1;  // 这样写就有问题了 !!! 虽然不知道为什么 
        for(it = mp.begin(); it != mp.end(); it++){
            int t = it->second; 
            ans *= 1ll*t*(t-1)/2%mod;
            ans %= mod;
        }
        //ans *= jc[cnt-1]%mod;  
        //ans *= fang[cnt-1]%mod;
        //ans %= mod;
        if (cnt == 1) printf("0\n");
        else
            printf("%lld\n", ans%mod);
    }
    
    return 0;
}

 

以上是关于2017.12.23 浙江工大 迎新赛的主要内容,如果未能解决你的问题,请参考以下文章

2020年浙江理工大学校赛同步赛

2017年浙工大迎新赛热身赛 J Forever97与寄信 数论/素数/Codeforces Round #382 (Div. 2) D. Taxes

河工大玲珑杯校赛随笔

2018.11.25 齐鲁工业大学ACM-ICPC迎新赛正式赛题解

Dest0g3 520迎新赛 Writeup

Dest0g3 520迎新赛 Writeup