现在的位置: 首页 > 综合 > 正文

UVA11174 Stand in a Line

2013年10月01日 ⁄ 综合 ⁄ 共 1393字 ⁄ 字号 评论关闭

题意是:

村子里有n个人,有多少种方式可以把他们排成一列,使得没人会排在他父亲的前面

然后给的关系大概是一个森林的样子

看训练指南中的讲解才豁然开朗

设f(i)是以节点i为根的子树的排列方法数

则 f(i) = f(c1)* f(c2) *f(c3) * f(c4).....* f(ck) * (s(i) - 1)! / ((s(c1)! * (s(c2))! .... * (s(ck))!)

s(i)表示的是以i为根的子树的节点个数

c1, c2,...ck为i的儿子们

这个式子首先是把各个子树的都排列好

然后子树之间,就类似有重复元素的全排列

然后观察这个式子

将每个非根节点带入上式子

可发现每个非根节点u以(s(u) - 1)!的形式出现在分子一次

以s(u)的形式出现在分母一次。

约分后相当于分子为1,分母为s(u)

得到最终的式子是、

f(root) = (s(root)-1)!/(s(i) * s(2) *... *s(n))

注意原图是个森林

所以我们可以建立一个超级祖先,将所有的根连上去

就成了一个根了

那么其实最终的解就是

n!/(s(1) * s(2) * ... * s(k))

那么因为我们要mod一个数

所以就要边算逆元边mod了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#define INF 111111111
#define MAXN 40005
#define MAXM 900005
using namespace std;
long long mod = 1000000007;
long long fac[MAXN];
vector<int>g[MAXN];
int son[MAXN];
int sz[MAXN];
int n, m;
long long fastmod(long long a, long long b, long long c)
{
    long long ret = 1;
    a %= c;
    for(; b; b >>= 1, a = (a * a) % c)
        if(b & 1)
            ret = ret * a % c;
    return ret;
}
void dfs(int u)
{
    sz[u] = 1;
    for(int i = 0; i < g[u].size(); i++)
    {
        dfs(g[u][i]);
        sz[u] += sz[g[u][i]];
    }
}
int main()
{
    fac[0] = 1;
    for(int i = 1; i < MAXN; i++) fac[i] = fac[i - 1] * (long long)i % mod;
    int T, u, v;
    scanf("%d", &T);
    while(T--)
    {
        memset(son, 0, sizeof(son));
        scanf("%d%d", &n, &m);
        for(int i = 0; i <= n; i++) g[i].clear();
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d", &u, &v);
            son[u] = 1;
            g[v].push_back(u);
        }
        for(int i = 1; i <= n; i++)
        {
            if(!son[i])
                dfs(i);
        }
        long long ans = fac[n];
        for(int i = 1; i <= n; i++)
        {
            long long k = fastmod(sz[i], mod - 2, mod);
            ans = ans * k % mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

抱歉!评论已关闭.