bzoj 1016 最小生成樹計數

2022-06-01 10:06:07 字數 1565 閱讀 7773

首先能發現乙個規律,就是重構最小生成樹的時候,一定不可能用一條權值較大的邊和一條權值較小的邊去替換他們中間的兩條邊。簡而言之,就是只能權值相同的邊相互替換。再進一步說,就是每種權值的邊的數目是一定的。

題目上說值相同的邊最多10條,那麼我們可以dfs選哪些,然後用並查集來判斷是否成環。這裡要注意,我們先kruskal把每種邊選幾條求出來,再按kruskal的順序dfs每一種,每dfs一種,我們就要把這些邊連起來(也就是邊dfs邊kruskal),這樣可以確保求出每種邊的組合是合法的。最後把它們乘起來就行了。

看一些題解上說如果相同的邊多了要用矩陣,表示不太懂......

minmst

1 #include2 #include3 #include4 #include5

#define maxn 120

6#define maxm 1200

7#define ms 31011

8using

namespace

std;

9struct

et10

e[maxm*2

];13

intf[maxm],v[maxm],c[maxm],l[maxm],r[maxm],q[maxm];

14bool

vis[maxm];

15int

n,m,tot,num,now,cnt;

16long

long

sum[maxm],ans;

1718

int find(int

i)19

2324

void dfs(int col,int k,int

ll)25

27for (int i=ll+1;i<=r[col];i++)

2838}39

}4041void add(int x,int y,int

z)42

4546

bool

cmp(et a,et b)

4750

51int

main()

5260 sort(e+1,e+m+1

,cmp);

61int j=0;62

for (int i=1;i<=m;i++)

63//

lisan

67for (int i=1;i<=m;i++)

6875 }//

kruskal

76 memset(f,0,sizeof

(f));

77 now=0;78

for (int i=1;i<=m;i++)

79//

dfs84

if (cnt1) ans=0; else ans=1;85

for (int i=1;i<=num;i++) if (sum[i]) ans*=sum[i],ans%=ms;

86 printf("

%d\n

",ans);

87return0;

88 }

BZOJ1016 最小生成樹計數

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

bzoj 1016 最小生成樹計數

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

BZOJ1016 最小生成樹計數 題解

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