UVA 11174 - Stand in a Line(組合遞歸計數)



大致題意:有n個人,給出m對關係,(a,b) 表示b是a的父親, 現在有多少種方案使他們排成一列,使得沒有人排在他們父親前面

(對1e9+7取模)

思路:

可見,給出了一顆森林,對於每棵樹,樹根顯然必須排第一位,然後對每棵子樹用組合統計位置方案樹,再乘以子樹的子問題方案數。

到這裏問題就算解決了,當然可以用dfs進行這種dp,但不妨人工迭代一下,每棵樹的答案是 

ans = (cnt(root)-1)!  / ( cnt(son1)*cnt(son2)*... )  

然後再轉化一下,加上虛根,把森林變成一顆樹,這樣得到的方案樹仍然不變,因爲根排列後必須佔第一個位置,這樣求解過程更簡潔

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
#define rep(i,n) for ( int i=0; i< int(n); i++ )
using namespace std;
typedef long long ll;
#define X first
#define Y second
#define PB push_back
#define MP make_pair
typedef pair<int,int> pii;

template <class T>
inline bool RD(T &ret) {
        char c; int sgn;
        if (c = getchar(), c == EOF) return 0;
        while (c != '-' && (c<'0' || c>'9')) c = getchar();
        sgn = (c == '-') ? -1 : 1 , ret = (c == '-') ? 0 : (c - '0');
        while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
        ret *= sgn;
        return 1;
}
template <class T>
inline void PT(T x) {
        if (x < 0) putchar('-') ,x = -x;
        if (x > 9) PT(x / 10);
        putchar(x % 10 + '0');
}

const int MOD = 1e9 + 7 ;
const int N = 4e4+100;

vector<int> G[N];
ll inv[N] ;
int qpow(int x) {
	int k = MOD - 2 ;
	ll ans = 1;
	ll m = x;
	while( k ) {
		if(k & 1) ans = (ans * m) % MOD ;
		k >>= 1;
		m = (m * m) % MOD;
	} 
	return ans ;
}
ll c[N];

void dfs(int u, int fa) {
	c[u] = 1;
	foreach(it, G[u]) {
		int v = *it;
		if( v == fa ) continue;
		dfs(v, u);
		c[u] += c[v];
	}
}
int main() {
	int T ;
	qpow(3);
	REP(i, N-10) inv[i] = qpow(i) ;
	RD(T);
	while(T --) {
		int n, m;
		RD(n), RD(m);
		REP(i, n) G[i].clear(), c[i] = 0;
		REP(i, m) {
			int u, fa;
			RD(u), RD(fa);
			G[fa].PB(u);
		}
		REP(i, n) if(!c[i]) dfs(i, 0);
		ll ans = 1;
		REP(i, n) ans = (ans * i) % MOD;
		REP(i, n) ans = (ans * inv[c[i]]) % MOD;
		PT(ans); puts("");
	}
}




發佈了308 篇原創文章 · 獲贊 11 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章