终于开始来补题了,两年前我就是个沙茶。
题目大意
给定$n$个点和$m,mle n - 1$个小于关系或者等于关系,问有多少种合法的序列满足这$m$个关系。
简要题解
第一眼就知道要先拓扑排序判断是否存在合法序列,然后很重要的一点是$mle n - 1$,所以得到的是森林而不是一般意义上的DAG,添加一个根把森林并成一棵树,考虑在树上DP就好了。
设以$u$为根的子树并成长度为$j$的序列(有等于关系的看做序列中的一个点)的方案数为$f[u][j]$,则$f[u][j]$的计算可以由儿子的答案合并起来得到。其实要解决的问题就是,给两个长度分别为$p,k$的序列,将其并成长度为$j$的序列的方案数($jle p+k$),可以这样想,先在$j$个位置中选$k$个用来放第二个序列中的元素,然后在这$k$个位置中选$p+k-j$个用来放第一个序列中的元素,这样两个序列中每个元素都有唯一确定的位置了,在DP的时候用一个新数组$g$来临时存合并的结果,$$f[u][j] = g[p] imes f[v][k] imes {jchoose k} imes {k choose p + k - j},vin son_u$$
手贱+脑残把$g$开成static,看到$g$的值还以为出了灵异事件QAQ
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace my_header { 4 #define pb push_back 5 #define mp make_pair 6 #define pir pair<int, int> 7 #define vec vector<int> 8 #define pc putchar 9 #define clr(t) memset(t, 0, sizeof t) 10 #define pse(t, v) memset(t, v, sizeof t) 11 #define bl puts("") 12 #define wn(x) wr(x), bl 13 #define ws(x) wr(x), pc(' ') 14 const int INF = 0x3f3f3f3f; 15 typedef long long LL; 16 typedef double DB; 17 inline char gchar() { 18 char ret = getchar(); 19 for(; (ret == ' ' || ret == ' ' || ret == ' ') && ret != EOF; ret = getchar()); 20 return ret; } 21 template<class T> inline void fr(T &ret, char c = ' ', int flg = 1) { 22 for(c = getchar(); (c < '0' || '9' < c) && c != '-'; c = getchar()); 23 if (c == '-') { flg = -1; c = getchar(); } 24 for(ret = 0; '0' <= c && c <= '9'; c = getchar()) 25 ret = ret * 10 + c - '0'; 26 ret = ret * flg; } 27 inline int fr() { int t; fr(t); return t; } 28 template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); } 29 template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); } 30 template<class T> inline char wr(T a, int b = 10, bool p = 1) { 31 return a < 0 ? pc('-'), wr(-a, b, 0) : (a == 0 ? (p ? pc('0') : p) : 32 (wr(a/b, b, 0), pc('0' + a % b))); 33 } 34 template<class T> inline void wt(T a) { wn(a); } 35 template<class T> inline void wt(T a, T b) { ws(a), wn(b); } 36 template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); } 37 template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); } 38 template<class T> inline T gcd(T a, T b) { 39 return b == 0 ? a : gcd(b, a % b); } 40 template<class T> inline T fpw(T b, T i, T _m, T r = 1) { 41 for(; i; i >>= 1, b = b * b % _m) 42 if(i & 1) r = r * b % _m; 43 return r; } 44 }; 45 using namespace my_header; 46 47 const int mod = 1e9 + 7; 48 const int maxN = 100 + 10; 49 int n, m; 50 int ind[maxN], fa[maxN], c[maxN][maxN]; 51 vector<int> go[maxN]; 52 int f[maxN][maxN]; 53 54 int findFa(int u) { 55 return fa[u] == u ? u : fa[u] = findFa(fa[u]); 56 } 57 58 void dp(int u) { 59 int g[maxN]; 60 memset(g, 0, sizeof g); 61 g[0] = 1; 62 for (int i = 0; i < (int)go[u].size(); ++i) { 63 int v = go[u][i]; 64 dp(v); 65 for (int j = 0; j <= n; ++j) 66 for (int k = 0; k <= n; ++k) 67 if (g[k] != 0) 68 for (int p = n; j <= p + k; --p) { 69 (f[u][j] += 1LL * g[k] * f[v][p] % mod * c[j][k] % mod * c[k][k + p - j] % mod) %= mod; 70 } 71 memcpy(g, f[u], sizeof f[u]); 72 memset(f[u], 0, sizeof f[u]); 73 } 74 memcpy(f[u] + 1, g, sizeof (int) * (maxN - 1)); 75 } 76 77 struct Data { 78 int u, v, op; 79 Data() { 80 fr(u); 81 op = gchar() == '='; 82 fr(v); 83 if (op == 1) 84 fa[findFa(u)] = findFa(v); 85 } 86 }; 87 88 int main() { 89 #ifdef lol 90 freopen("4013.in", "r", stdin); 91 freopen("4013.out", "w", stdout); 92 #endif 93 94 fr(n, m); 95 96 c[0][0] = 1; 97 c[1][1] = c[1][0] = 1; 98 for (int i = 2; i <= n; ++i) { 99 c[i][0] = 1; 100 for (int j = 1; j <= i; ++j) 101 c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod; 102 } 103 for (int i = 1; i <= n; ++i) 104 fa[i] = i; 105 Data *d = new Data[m]; 106 for (int i = 0; i < m; ++i) { 107 int u = findFa(d[i].u); 108 int v = findFa(d[i].v); 109 if (u != v) { 110 go[u].pb(v); 111 ++ind[v]; 112 } 113 } 114 115 queue<int> q; 116 for (int i = 1; i <= n; ++i) { 117 if (findFa(i) != i) 118 continue; 119 if (ind[i] == 0) { 120 q.push(i); 121 go[0].pb(i); 122 } 123 } 124 while (!q.empty()) { 125 int u = q.front(); 126 q.pop(); 127 for (int i = 0; i < (int)go[u].size(); ++i) { 128 int v = go[u][i]; 129 --ind[v]; 130 if (ind[v] == 0) 131 q.push(v); 132 } 133 } 134 for (int i = 1; i <= n; ++i) 135 if (ind[i] != 0) { 136 wt(0); 137 return 0; 138 } 139 140 dp(0); 141 142 int ans = 0; 143 for (int i = 1; i <= n + 1; ++i) 144 (ans += f[0][i]) %= mod; 145 wt(ans); 146 147 return 0; 148 }