BZOJ1016 最小生成樹計數

2022-05-02 03:48:06 字數 1374 閱讀 4562

題面描述

最小生成樹計數

給定乙個n個點、m條邊的無向圖,求其最小生成樹的個數。相同邊權的邊不會超過10條。

思維難度:提高+;**難度:提高+;

題解:

先給出兩個引理:

1.克魯斯卡爾求最小生成數實際上是分成很多個階段的,你可以感受到:很多邊權相同的邊因為排序順序不同,導致它們被訪問的順序不同。但每處理完乙個邊權相同的邊集,當前圖的一些性質(連通塊數、邊數、代價數)是一樣的,並不會因為同邊權集中的邊的排序順序改變而改變。換句話說,圖的本質可能會變,但它的「表現」是不變的。

2.不同的階段產生的邊,對於每棵最小生成樹,是恆定的,且每個階段在保證正確的如何選擇,對後面的選擇沒有影響。統計答案時,應該使用乘法原理。

那麼我們接下來有兩種方法:matrix tree 或者 爆搜2333

注意到題麵中寫的「相同邊權的邊不超過10條」,直接指數級爆搜選不選就可以了。並查集時不能用路徑壓縮,因為你要有撤銷功能。

提交次數:2次 第一次是因為沒刪除錯**。b站不顯示錯誤輸出真是好坑啊。

這題啟示我們:省選題也有指數級爆搜的舞台(ohhh)。

#include #include #include #include #include #include #include #define ll long long int

#define ls (x << 1)

#define rs (x << 1 | 1)

using namespace std;

const int mod = 31011;

struct nodee[mod];

int n,m,ans,flag,fa[mod],vis[mod],ans;

int gi()

while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();

return x*res;

}ll gl()

while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();

return x*res;

}bool cmp(const node &a,const node &b){return a.w

bzoj 1016 最小生成樹計數

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

bzoj 1016 最小生成樹計數

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

BZOJ1016 最小生成樹計數 題解

顯然的是,不同的生成樹的不同權值的邊數一定是一樣的 我們可以先跑一遍kruskal把每種邊需要多少條記錄一下 然後由於相同權值的邊不超過10條,所以在相同權值的邊內部搜一下,看哪些邊加進原圖無環 然後乘法原理和前面的答案乘一下 不同的選擇方法對後面的並查集的更新肯定是沒有影響的,不然一開始的krus...