• HNOI2015 实验比较


    终于开始来补题了,两年前我就是个沙茶。

    题目大意

    给定$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 }
  • 相关阅读:
    DataItem 的使用[转帖]
    xmpp协议阅读总结
    smart pointer shared_from_this的使用
    std IO库, stringstream, 简看1
    const成员函数, const member function
    enum 随笔
    分隔和截断字符串, boost string algorithm library中的split和trim
    C++中异常处理
    boost::thread中的锁
    函数对象function object 以及boost::bind的一点了解
  • 原文地址:https://www.cnblogs.com/ichn/p/6391710.html
Copyright © 2020-2023  润新知