SRM 562

這題分兩種情況考慮。

1、2*k<=n

這種情況需要中間一段(n-2*k+2長度)是一條直線,直線兩端分別接k-1個點,那麼這k-1個點形成一個星型,只要保證葉子節點比內部節點編號小就滿足情況(直線編號小的那端)。dp搞定。


2、2*k>=n

這個中間一坨需要聯通,然後看成一個球,向外也是星形射出,外面星形的部分和上面一樣,球的部分可以全排列。

我代碼具體做法:枚舉一個點(假設是這個球編號最小的點),然後樹形dp[i][left][right],表示第i個節點爲根的子樹,其中left個節點放前面,right個節點放後面(剩下那些就是球的一部分)。看上去是n^6,複雜度沒那麼高而且n=20


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>

using namespace std;

class InducedSubgraphs {
public:
	int getCount(vector<int> , vector<int> , int);
};
/////////////////////////////////
long long pmod = 1000000009;
long long C[55][55];
long long ba[55];
void pre() {
	int i, j;
	for (i = 0; i < 55; ++i) {
		C[i][0] = C[i][i] = 1;
		for (j = 1; j < i; ++j)
			C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % pmod;
	}
	ba[0] = 1;
	for (i = 1; i < 55; ++i)
		ba[i] = ba[i - 1] * i % pmod;
}

//////////////////////////////////
int n, k;
vector<int> nt[55];
int path[55];
bool flag1;
int len2;
bool dfs1(int i, int fa, int target, int id) {
	path[id] = i;
	if (i == target) {
		len2 = id + 1;
		if (id + 1 != n - 2 * k + 2)
			flag1 = false;
		for (int j = 1; j < len2 - 1; ++j) {
			if (nt[path[j]].size() != 2)
				flag1 = false;
		}
		return true;
	}
	for (int j = 0; j < nt[i].size(); ++j) {
		if (nt[i][j] == fa)
			continue;
		if (dfs1(nt[i][j], i, target, id + 1))
			return true;
	}
	return false;
}
int cnt[55];
int dfscnt(int i, int fa) {
	int ret = 1;
	for (int j = 0; j < nt[i].size(); ++j) {
		if (nt[i][j] == fa)
			continue;
		ret += dfscnt(nt[i][j], i);
	}
	return cnt[i] = ret;
}
long long dfsans(int i, int fa) {
	long long ret = 1;
	int k = cnt[i] - 1;
	for (int j = 0; j < nt[i].size(); ++j) {
		if (nt[i][j] == fa)
			continue;
		ret = ret * C[k][cnt[nt[i][j]]] % pmod;
		ret = ret * dfsans(nt[i][j], i) % pmod;
		k -= cnt[nt[i][j]];
	}
	return ret;
}
int gao1() {
	long long ans = 0;
	int i1, i2;
	for (i1 = 0; i1 < n; ++i1) {
		for (i2 = 0; i2 < n; ++i2) {
			if (i1 == i2)
				continue;
			flag1 = true;
			len2 = 0;
			dfs1(i1, -1, i2, 0);
			if (!flag1)
				continue;
			if (dfscnt(i1, path[1]) != k || dfscnt(i2, path[len2 - 2]) != k)
				continue;
			ans += dfsans(i1, path[1]) * dfsans(i2, path[len2 - 2]) % pmod;
			ans %= pmod;
		}
	}
	return ans;
}
int m;
long long dp[50][30][30];
int dfs(int i, int fa) {
	int r, s, rr, ss;
	int cnt = 1;
	dp[i][0][0] = 1;
	for (int j = 0; j < nt[i].size(); ++j) {
		if (nt[i][j] == fa)
			continue;
		int k = nt[i][j];
		cnt += dfs(k, i);
		for (r = m; r >= 0; --r) {
			for (s = m; s >= 0; --s) {
				if (dp[i][r][s] == 0)
					continue;
				for (rr = 0; rr + r <= m; ++rr) {
					for (ss = 0; ss + s <= m; ++ss) {
						if (dp[k][rr][ss] == 0)
							continue;
						if (rr == 0 && ss == 0)
							continue;
						dp[i][r + rr][s + ss] += dp[i][r][s] * dp[k][rr][ss]
								% pmod * C[r + rr][r] % pmod * C[s + ss][s]
								% pmod;
						dp[i][r + rr][s + ss] %= pmod;
					}
				}
			}
		}
	}
	dfscnt(i, fa);
	long long p = dfsans(i, fa);
	if (cnt <= m) {
		dp[i][cnt][0] += p;
		dp[i][cnt][0] %= pmod;
		dp[i][0][cnt] += p;
		dp[i][0][cnt] %= pmod;
	}
	return cnt;
}

int gao2() {
	int i;
	long long ans = 0;
	m = n - k;
	for (i = 0; i < n; ++i) {
		memset(dp, 0, sizeof(dp));
		dfs(i, -1);
		ans += dp[i][m][m];
		ans %= pmod;
	}
	return ans * ba[2 * k - n - 1] % pmod;
}
int InducedSubgraphs::getCount(vector<int> edge1, vector<int> edge2, int K) {
	int i;
	k = K;
	n = edge1.size() + 1;
	for (i = 0; i < n; ++i)
		nt[i].clear();
	for (i = 0; i < n - 1; ++i) {
		nt[edge1[i]].push_back(edge2[i]);
		nt[edge2[i]].push_back(edge1[i]);
	}
	pre();
	if (k == 1)
		return ba[n];
	if (2 * k <= n)
		return gao1();
	else
		return gao2();
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章