先並查集合並『=』,因為所有的xi互不相同,所以合併完後應該是乙個森林,如果出現環就無解。
我們新建乙個根連向所有入度為0的點,就變成了一棵樹,考慮樹形dp。
因為只要兩點不是其中一點是另一點的祖先的關係,他們就可以劃『=』因為大小關係不確定,所以將『=』連線的看做一塊,f[
i][j
] 表示以
i 為根的子樹分成了j塊
轉移的話,不合併塊就是排列組合問題,如果合併塊的話,假設不同子樹的
i 個塊和
j個塊合併,合併成
k 塊,因為可以推出一棵子樹上的塊不能合併(否則方案數會算重複),所以問題可以轉化成
i個1,
j 個0,放進
k個格仔,同乙個格仔不能放多個1或多個0,先將1全放進去,剩下的用0補滿,多餘的j−
(k−i
) 個0在
i 個位置選j−
(k−i
)個位置,那麼方案數就是ci
k∗cj
−(k−
i)i
a1,a2
是x的兩個孩子,合併後視作新的孩子a3
,a3 繼續和其他孩子合併f[
a3][
i]=f
[a1]
[j]∗
f[a2
][k]
∗cji
∗ck−
(i−j
)j最後合併到只剩乙個孩子
y ,因為節點x不能和其子樹上的點合併,所以f[
x][i
]=f[
y][i
−1]code:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int maxn = 210;
const ll mod = 1e9+7;
struct edge
edge(int _y,int _nex)
}a[maxn<<1]; int root,len,fir[maxn];
void ins(int
x,int
y)int
q[maxn][3],n,m;
int _in[maxn],fa[maxn];
int find_f(int
x)ll c[maxn][maxn],f[maxn][maxn],siz[maxn],sizg[maxn],g[maxn][maxn];
bool v[maxn],mp[maxn][maxn];
void dfs(int
x) else
sizg[x]+=siz[y];
for(int i=1;i<=sizg[x];i++) }}
if(!sizg[x]) f[x][1]=1;
else
for(int i=2;i<=siz[x];i++) f[x][i]=g[x][i-1];
}bool judge(int
x)int main()
for(int i=1;i<=m;i++)
}memset(_in,0,sizeof _in);
for(int i=1;i<=m;i++)}}
for(int i=1;i<=n;i++)
}root=n+1;
for(int i=1;i<=n;i++)
if(_in[find_f(i)]==0&&!mp[root][fa[i]])
dfs(root);
ll ret=0;
for(int i=1;i<=siz[root];i++) (ret+=f[root][i])%=mod;
printf("%lld\n",ret);
return
0;}
BZOJ 4013 HNOI2015 實驗比較
樹dp 組合數 網上題解很多,這裡就放個有注釋的 code 1 include 2 include 3 include 4 include 5 include 6 include 7 define maxn 110 8 define mod 1000000007 9using namespace s...
bzoj4013 HNOI2015 實驗比較
傳送門 思路 首先把等於的縮成乙個點,由好的向壞的連邊,有環肯定無解。然後題目裡說 小 d都最多隻記住了某一張質量不比 i差的另一張 ki 那就是每個點就最多只有一條入邊,那存在合法方案的圖就一定是森林。加乙個虛根,這可以樹形dp了。假設f i j 表示i號點的子樹中的所有點構成的有且只有j個小於號...
4013 HNOI2015 實驗比較
time limit 5 sec memory limit 512 mb submit 535 solved 268 submit status discuss 小d n 張,編號為1 到 n。實驗分若干輪進行,在每輪實驗中,小 d會被要求 某兩張隨機選取的,然後小d 需要根據他自己主觀上的判斷確定...