题目:http://community.topcoder.com/stat?c=problem_statement&pm=12951&rd=15837
参考:http://apps.topcoder.com/wiki/display/tc/SRM+604
dp状态不好想,而且用dfs来构造树也不好想,很难的题目。
代码:
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <string>
#include <vector>
#include <stack>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <ctime>
#include <climits>
using namespace std;
#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)
typedef pair<int, int> pii;
typedef long long llong;
typedef pair<llong, llong> pll;
#define mkp make_pair
/*************** Program Begin **********************/
const int MOD = 1e9 + 7;
const int MAX = 55;
long long dp[MAX][MAX][MAX]; // dp[x][e][k] 表示以x为根的树,若不考虑其前e个孩子,能选出顶点数为k的且以x为根的子树的种数
int g[MAX][MAX]; // g[x][e] 表示顶点x的第e个孩子
int degree[MAX]; // degree[x] 表示顶点x的孩子数
class FoxConnection2 {
public:
// 使用dfs构造树, 求出各顶点的孩子
void dfsMakeTree(int x, int parent, vector <int> & A, vector <int> & B)
{
degree[x] = 0;
for (int i = 0; i < A.size(); i++) {
if (x == A[i] - 1 && parent != B[i] - 1) { // B[i] - 1 是 x的孩子
g[x][ degree[x] ] = B[i] - 1; // 顶点从0开始编号
++degree[x];
dfsMakeTree( B[i] - 1, x, A, B ); // 构造孩子树
}
if (x == B[i] - 1 && parent != A[i] - 1) {
g[x][ degree[x] ] = A[i] - 1;
++degree[x];
dfsMakeTree( A[i] - 1, x, A, B);
}
}
}
int rootedWays(int x, int e, int k)
{
long long & res = dp[x][e][k];
if (e == degree[x]) {
return (k == 1 ? 1 : 0);
}
if (res != -1) {
return res;
}
res = rootedWays(x, e + 1, k); // 第一颗子树不提供,全部由剩下的树提供
for (int i = 1; i < k; i++) { // 第一颗子树提供i个,剩下的树提供k-i个
res += rootedWays(g[x][e], 0, i) * rootedWays(x, e + 1, k - i);
res %= MOD;
}
return res;
}
int ways(vector <int> A, vector <int> B, int k) {
long long res = 0;
memset(dp, -1, sizeof(dp));
memset(degree, 0, sizeof(degree));
memset(g, 0, sizeof(g));
dfsMakeTree(0, -1, A, B);
for (int i = 0; i < A.size() + 1; i++) {
res += rootedWays(i, 0, k);
res %= MOD;
}
return res;
}
};
/************** Program End ************************/