BZOJ 1016 最小生成樹計數(矩陣樹定理)

2022-05-19 20:35:22 字數 1075 閱讀 8995

我們把邊從小到大排序,然後依次插入一種權值的邊,然後把每乙個聯通塊合併。

然後當一次插入的邊不止一條時做矩陣樹定理就行了。算出有多少種生成樹就行了。

剩下的交給乘法原理。

實現一不小心就會讓程式變得很醜

#include#include#include#include#includeusing namespace std;

#define int long long

const int mod=31011;

const int n=110;

int fa[n],a[n][n][n],n,m,b[1010],cnt[n],id[n],w[n],ans[n],mmp[n];

struct edgee[1010];

bool cmp(edge a,edge b)

while(ch>='0'&&ch<='9')

return sum*f;

}void init()

signed main()

int x=find(e[line].u),y=find(e[line].v);

if(x!=y)fa[x]=y;

line++;

} for(int j=1;j<=n;j++)fa[j]=find(j);

for(int j=1;j<=n;j++)id[j]=++cnt[fa[j]];

for(int j=now;j<=line-1;j++)

for(int j=1;j<=n;j++)w[j]=1;

for(int j=1;j<=n;j++)w[fa[j]]=w[fa[j]]*ans[j]%mod;

for(int j=1;j<=n;j++)

if(cnt[j])

for(int j=line;j<=m;j++)e[j].u=mmp[fa[e[j].u]],e[j].v=mmp[fa[e[j].v]];

now=line;n=tmp;

} if(n>1)printf("0");

else printf("%lld",ans[1]);

return 0;

}

BZOJ1016 最小生成樹計數

題面描述 最小生成樹計數 給定乙個n個點 m條邊的無向圖,求其最小生成樹的個數。相同邊權的邊不會超過10條。思維難度 提高 難度 提高 題解 先給出兩個引理 1.克魯斯卡爾求最小生成數實際上是分成很多個階段的,你可以感受到 很多邊權相同的邊因為排序順序不同,導致它們被訪問的順序不同。但每處理完乙個邊...

bzoj 1016 最小生成樹計數

首先能發現乙個規律,就是重構最小生成樹的時候,一定不可能用一條權值較大的邊和一條權值較小的邊去替換他們中間的兩條邊。簡而言之,就是只能權值相同的邊相互替換。再進一步說,就是每種權值的邊的數目是一定的。題目上說值相同的邊最多10條,那麼我們可以dfs選哪些,然後用並查集來判斷是否成環。這裡要注意,我們...

bzoj 1016 最小生成樹計數

給定乙個簡單無向有權圖,求其最小生成樹的個數。在我們用kruskal計算最小生成樹時,由於相同權值的邊選擇的順序是隨機的,所以我們最小生成樹就也許有很多。對於同一權值的邊,我們不論用什麼順序 掃過 最終的得到的無向森林的連通性一定是一樣的,即對後面的邊是否加入的影響也是一樣的,所以可以根據這一點將最...