HNOI2015 實驗比較
題目大意
給定一些數字的大小關係,有>,<和=三種情況。保證輸入給定的關係對於每個數來說,<=它的數字最多隻有一個。求所有數字有多少種不同的相對大小關係。
。
題解
首先對於等號可以直接縮點,關注到<=某個數字的限制最多隻有一個,因此我們從小的向大的連邊,形成多棵基環樹和樹。顯然,如果圖中有環則無解,因此只剩下來樹。為了方便處理,我們新建點0,向每個樹的根連邊。
接下來顯然是樹形dp,考慮到序列中可能存在相等的情況,於是令表示dp到點,子樹形成的序列中不同數字的個數為。我們考慮如何合併兩棵子樹。
同樣的,我們把相同的數字看成一個點,那麼合成一個序列之後,兩個等號不可能相鄰地出現。那麼就會形成若干對相等的數字,每對中兩個數字分別來自兩棵子樹。剩下的數字用組合數算一下就行了。
我們還需要表示長度為的序列中畫個不相鄰等號的方案數,顯然。
於是就可以dp了,複雜度。
#include <bits/stdc++.h>
namespace IOStream {
const int MAXR = 10000000;
char _READ_[MAXR], _PRINT_[MAXR];
int _READ_POS_, _PRINT_POS_, _READ_LEN_;
inline char readc() {
#ifndef ONLINE_JUDGE
return getchar();
#endif
if (!_READ_POS_) _READ_LEN_ = fread(_READ_, 1, MAXR, stdin);
char c = _READ_[_READ_POS_++];
if (_READ_POS_ == MAXR) _READ_POS_ = 0;
if (_READ_POS_ > _READ_LEN_) return 0;
return c;
}
template<typename T> inline void read(T &x) {
x = 0; register int flag = 1, c;
while (((c = readc()) < '0' || c > '9') && c != '-');
if (c == '-') flag = -1; else x = c - '0';
while ((c = readc()) >= '0' && c <= '9') x = x * 10 - '0' + c;
x *= flag;
}
template<typename T1, typename ...T2> inline void read(T1 &a, T2&... x) {
read(a), read(x...);
}
inline int reads(char *s) {
register int len = 0, c;
while (isspace(c = readc()) || !c);
s[len++] = c;
while (!isspace(c = readc()) && c) s[len++] = c;
s[len] = 0;
return len;
}
inline void ioflush() { fwrite(_PRINT_, 1, _PRINT_POS_, stdout), _PRINT_POS_ = 0; fflush(stdout); }
inline void printc(char c) {
if (!c) return;
_PRINT_[_PRINT_POS_++] = c;
if (_PRINT_POS_ == MAXR) ioflush();
}
inline void prints(const char *s, char c) {
for (int i = 0; s[i]; i++) printc(s[i]);
printc(c);
}
template<typename T> inline void print(T x, char c = '\n') {
if (x < 0) printc('-'), x = -x;
if (x) {
static char sta[20];
register int tp = 0;
for (; x; x /= 10) sta[tp++] = x % 10 + '0';
while (tp > 0) printc(sta[--tp]);
} else printc('0');
printc(c);
}
template<typename T1, typename ...T2> inline void print(T1 x, T2... y) {
print(x, ' '), print(y...);
}
}
using namespace IOStream;
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int MAXN = 105, MOD = 1000000007;
struct Edge { int to, next; } edge[MAXN];
int head[MAXN], deg[MAXN], par[MAXN], n, m, tot;
int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); }
inline void addedge(int u, int v) {
edge[++tot] = (Edge) { v, head[u] };
head[u] = tot;
}
int mp[MAXN][MAXN], fr[MAXN], to[MAXN], sz[MAXN], que[MAXN];
ll f[MAXN][MAXN], g[MAXN][MAXN], C[MAXN][MAXN], h[MAXN][MAXN];
void dfs(int u) {
f[u][0] = 1;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
dfs(v);
for (int j = 0; j <= sz[u]; j++)
for (int k = 1; k <= sz[v]; k++)
for (int l = 0; l <= j && l <= k; l++)
(g[u][j + k - l] += h[j + k][l] % MOD * C[j + k - l - l][j - l] % MOD * f[u][j] % MOD * f[v][k]) %= MOD;
sz[u] += sz[v];
for (int j = 0; j <= sz[u]; j++)
f[u][j] = g[u][j], g[u][j] = 0;
}
for (int j = ++sz[u]; j > 0; j--) f[u][j] = f[u][j - 1];
f[u][0] = 0;
}
int main() {
read(n, m);
for (int i = 1; i <= n; i++) par[i] = i;
int cnt = 0;
for (int i = 1; i <= m; i++) {
int a, b; char o[5];
read(a), reads(o), read(b);
if (o[0] == '<') ++cnt, fr[cnt] = a, to[cnt] = b;
else par[find(a)] = find(b);
}
for (int i = 1; i <= cnt; i++) {
int x = find(fr[i]), y = find(to[i]);
if (x != y && !mp[x][y]) mp[x][y] = 1, addedge(x, y), ++deg[y];
}
int he = 0, ta = cnt = 0;
for (int i = 1; i <= n; i++) if (par[i] == i) {
if (!deg[i]) addedge(0, i), que[ta++] = i;
++cnt;
}
while (he < ta) {
int u = que[he++];
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (!(--deg[v])) que[ta++] = v;
}
}
if (ta != cnt) return puts("0") * 0;
h[0][0] = C[0][0] = 1;
for (int i = 1; i <= n; i++) {
C[i][0] = 1;
for (int j = 1; j <= i; j++)
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
}
for (int i = 1; i <= n; i++)
for (int j = 0; j * 2 <= i; j++) {
h[i][j] = h[i - 1][j];
if (i > 1 && j > 0) h[i][j] = (h[i][j] + h[i - 2][j - 1]) % MOD;
}
dfs(0);
ll res = 0;
for (int i = 1; i <= n + 1; i++) res += f[0][i];
printf("%lld\n", res % MOD);
return 0;
}
相關文章
- Vue2 和 Vue3 效能比較小實驗Vue
- 分享投訴順豐經歷,體驗確實比較不錯
- 前端比較實用的CSS前端CSS
- BST查詢結構與折半查詢方法的實現與實驗比較
- js 深比較和淺比較JS
- 如何比較版本號--Python實現Python
- Oracle date 型別比較和String比較Oracle型別
- 幾種分散式呼叫鏈監控元件的實踐與比較(二)比較分散式元件
- 比較集合
- Integer比較
- 效能比較
- 字串比較字串
- 原型設計工具比較及實踐原型
- PostgreSQL與Rust的聚合實現比較SQLRust
- 實現saas多租戶方案比較
- 【譯】Css Grid VS Flexbox: 實踐比較CSSFlex
- 比較檔案是否相同,(比較MD5值)
- [C++] 自定義C++比較器比較大小C++
- Go和Python比較的話,哪個比較好?GoPython
- 哪些開源雲工具比較實用呢?
- 有哪些比較實用的全球http代理HTTP
- 列舉比較
- 常用 NoSQL 比較SQL
- Jsonunit 比較jsondiffJSON
- Integer的比較
- easyExcel & poi 比較Excel
- 主流CRM比較
- ==與equals比較
- Java 比較器Java
- CORS/JSONP比較CORSJSON
- 數字比較
- PHP比較字串PHP字串
- 驗證Kubernetes YAML的六個工具比較 - learn8sYAML
- 0503對比實驗歸因
- Linux中11個比較實用的命令列Linux命令列
- 如何實現不完全字典比較的 helper
- 通過Comparable來實現對自身的比較
- 前端動畫效果實現的簡單比較前端動畫