description
現在給出了乙個簡單無向加權圖。你不滿足於求出這個圖的最小生成樹,而希望知道這個圖中有多少個不同的
最小生成樹。(如果兩顆最小生成樹中至少有一條邊不同,則這兩個最小生成樹就是不同的)。由於不同的最小生
成樹可能很多,所以你只需要輸出方案數對31011的模就可以了。
input
第一行包含兩個數,n和m,其中1<=n<=100; 1<=m<=1000; 表示該無向圖的節點數和邊數。每個節點用1~n的整
數編號。接下來的m行,每行包含兩個整數:a, b, c,表示節點a, b之間的邊的權值為c,其中1<=c<=1,000,000,0
00。資料保證不會出現自回邊和重邊。注意:具有相同權值的邊不會超過10條。
output
輸出不同的最小生成樹有多少個。你只需要輸出數量對31011的模就可以了。
sample input
4 6
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1
sample output
8 這篇文章講的real清楚 下面是引用的原文
首先需要乙個結論,對於乙個圖的不同最小生成樹,每種方案所包含的每種權值的邊的數量一定一致。換句話說,把每種方案包含的所有邊的邊權都寫下來,寫出來的序列一定都一樣。關於這個結論的說明放在最後。
這樣的話,可以先做一遍kruskal,記下每種邊權的使用次數,然後對於每種邊權進行dfs,判斷有多少種合法的組合方式【一種方案合法意味著:1.加入每條邊時,邊的兩端點一定屬於不同的並查集,也就是仍然要符合kruskal的要求。2.加入的總邊數等於開始統計的使用次數。第一條要求也就決定了不能用組合數進行計算,只能dfs,而因為相同邊權的邊不超過10,再加上一些最簡單的剪枝,執行速度很快。】,然後用乘法原理即可。
注意:
1.dfs的時候要回溯,所以這裡的並查集不能進行路徑壓縮。
2.處理完每種邊之後要把這些邊加上去,這才是kruskal的過程。
3.考慮圖不連通,即不存在最小生成樹的情況。
最後說一下原理。考慮kruskal的過程,只有當這一權值的邊全部考慮之後才會考慮權值比他大的邊。舉個最簡單的例子,假設有兩種方案,第一種方案有邊x1,x4,第二種有邊x2,x3,且x1< x2< x3< x4。因為一條邊只能連線兩個連通塊,那麼x2,x3中一定有乙個能起到x4的作用,那麼這個能起作用的點和x1組成的方案才是最小生成樹。
既然這樣,不同的方案從何而來呢?來自於相同的權值的邊,在排序後的順序不同,而他們又起著相同的作用(也就是連線相同的聯通塊)【因為如果作用不一樣的話,他們應該都被納入方案】,那麼先考慮這個和先考慮那個就會得出不同的方案。
於是,我們對每一組權值相同的邊,知道了他們總的使用次數以後,進行暴力的列舉統計方案數。因為我們知道,不管怎麼選,最後的結果,也就是給後面帶來的影響,都是相同的【因為如果影響不同,那麼就不應該現在從中挑選,當初kruskal的時候應該都選進來。】
那麼這種做法,和直接暴力列舉的區別就顯現了。暴力列舉是整個的指數級,而這種做法是把總數分成很多小塊,在每一塊裡暴力列舉,最後的複雜度是每一塊的指數相加,自然小了很多。
相當於我先用kruskal做出我的最小生成樹 然後記錄下一共使用了多少種權值
因為我是排好序的所以我給每個權值分段 並且記錄下我每種權值都用了多少
然後根據上面的證明 我權值連線的應該都是相同的聯通塊才行
每次做完一種權值後就給他們連起來 (ps:造成的效果是一樣的)所以隨便連就可以了
#include
#include
#define mod 31011
#define n 110
#define m 1100
using namespace std;
inline int read()
return x;
}struct nodedata[m];
struct node1group[m];
inline bool cmp(node a,node b)
void dfs(int id,int step,int now)
dfs(id,step+1,now);
int xx=find(data[step].x),yy=find(data[step].y);
if (xx!=yy)
}int main()
sort(data+1,data+m+1,cmp);int g=0,cnt=0;
for (int i=1;i<=n;++i) fa[i]=i;
for (int i=1;i<=m;++i)
}group[g].r=m;
if (cnt1)
int ans=1;
for (int i=1;i<=n;++i) fa[i]=i;
for (int i=1;i<=g;++i)
}printf("%d\n",ans);
return
0;}
bzoj1016 JSOI2008 最小生成樹計數
現在給出了乙個簡單無向加權圖。你不滿足於求出這個圖的最小生成樹,而希望知道這個圖中有多少個不同的最小生成樹。如果兩顆最小生成樹中至少有一條邊不同,則這兩個最小生成樹就是不同的 由於不同的最小生成樹可能很多,所以你只需要輸出方案數對31011的模就可以了。第一行包含兩個數,n和m,其中1 n 100 ...
bzoj 1016 kruscal 乘法原理
題意 求n個點 m條邊的不同的最小生成樹的方案數 每種邊權的邊數量固定 作用固定 先做一遍最小生成樹,求出每種邊權在最小生成樹中的數量num i 再從小到大對每種邊權進行dfs,求出對於第i種邊權,有多少種滿足num i 的取法 根據乘法原理乘上即可 對於已經處理完的第i種邊權,把該種邊權所有的邊能...
1016 JSOI2008 最小生成樹計數
description 現在給出了乙個簡單無向加權圖。你不滿足於求出這個圖的最小生成樹,而希望知道這個圖中有多少個不同的 最小生成樹。如果兩顆最小生成樹中至少有一條邊不同,則這兩個最小生成樹就是不同的 由於不同的最小生 成樹可能很多,所以你只需要輸出方案數對31011的模就可以了。input 第一行...