码迷,mamicode.com
首页 > 其他好文 > 详细

uva 11174 Stand in a Line

时间:2015-08-05 20:05:11      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:

//    uva 11174 Stand in a Line
//
//    题目大意:
//
//        村子有n个村民,有多少种方法,使村民排成一条线
//    使得没有人站在他父亲的前面.
//
//    解题思路:
//
//        换成模型,先将森林变成一棵树,这样就直观多了,对于
//    一个节点,他的子节点排列时没有任何要求,而子排列中会有
//    限制,将这些限制先提取出来,就可以将所有的视为相同的了,
//    然后就是有重复元素的全排列问题.设s(i)为以i节点为根的子树
//    f(i)为以i为根的子树的排法,
//        f(i) = f(c1)f(c2)...(s(i)-1)! / (s(c1)!s(c2)!...s(ck)!);
//    cj为i的第j个儿子.递归发现所有的非根节点的f带入上式,发现所有的
//    非根节点u都会以(s(u)-1)!出现在以他为根的分子中,s(u)出现在他父
//    节点的分母中,约分之后,分子为1,分母为s(u),这样就得到了一个
//    简化的式子,:
//        f(root) = (s(root)-1)!/(s(c1)s(c2)...s(ck));
//    s(root) = n + 1;
//    最后的结果为n!除以所有的s(i).

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int MAX_N = 40008;

typedef long long ll;

vector<int> g[MAX_N];

const ll MOD = 1e9 + 7;

int cnt[MAX_N];
bool vis[MAX_N];
int n,m;

void dfs(int u){
    vis[u] = 1;
    cnt[u]=1;
    for (int i=0;i<g[u].size();i++){
        int v = g[u][i];
        if (vis[v])
            continue;
    
        dfs(v);
        
        cnt[u] += cnt[v]; 
    }
}

void exgcd(ll a,ll b,ll &x,ll &y){
    if (b==0){
        x = 1;
        y = 0;
        return ;
    }
    exgcd(b,a%b,x,y);
    ll temp = x;
    x = y;
    y = temp - a / b * y;
}

void print(){
    for (int i=1;i<=n;i++){
        printf("%d ",cnt[i]);
    }
    cout << endl;
}

void input(){
    scanf("%d%d",&n,&m);
    ll ans = 1;
    memset(cnt,0,sizeof(cnt));
    memset(vis,0,sizeof(vis));
    for (int i=1;i<=n;i++){
        ans = ans * i % MOD;
        g[i].clear();
    }
    int u,v;
    for (int i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }

    for (int i=1;i<=n;i++){
        if (!vis[i])
            dfs(i);
    }
//    print();
    ll p = 1;

    for (int i=1;i<=n;i++){
        p = p * cnt[i] % MOD;
    }

    //printf("cnt = %lld\n",p);

    ll x,y;
    
    exgcd(MOD,p,x,y);
    
    cout << ans * ((y + MOD )%MOD) % MOD << endl; 

}

int main(){
    int t;
//    freopen("1.txt","r",stdin);
    scanf("%d",&t);
    while(t--){
        input();
    }
}

 

uva 11174 Stand in a Line

标签:

原文地址:http://www.cnblogs.com/KingJourney/p/4705621.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!