1016 JSOI2008 最小生成樹計數

2021-08-03 05:51:57 字數 1442 閱讀 8395

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 61 2 1

1 3 1

1 4 1

2 3 2

2 4 1

3 4 1

sample output

在乙個連通圖中不同的最小生成樹所使用的每個不同邊權次數都是相等的。所以先跑一次求出每個邊權使用的次數,然後用dfs搜尋每種邊權使用的可能最後相乘。

#include#include#includeusing namespace std;

#define ll long long

const int maxm = 1005;

const int mod = 31011;

struct node

};node a[maxm];

typedef struct

h;h b[maxm];

int p[105], len = 0;

ll ans = 1, rev = 0;

int find(int k);

void dfs(int id, int now, int k);

int main()

int t1 = find(a[i].u), t2 = find(a[i].v);

if (t1 != t2)

}b[len].r = m;

if (sum != n - 1)

for (i = 1;i <= n;i++)

p[i] = i;

for (i = 1;i <= len;i++) }

printf("%lld\n", ans);

return 0;

}int find(int k)

void dfs(int id, int now, int k)

int t1 = find(a[now].u), t2 = find(a[now].v);

if (t1 != t2)

dfs(id, now + 1, k);

}

1016 JSOI2008 最小生成樹計數

orz,感覺對最小生成樹的理解又加進了一步。ps 不得不說對於經典演算法的 是永無止境的,只能通過交流和增長見識來學習和體會,自己研究確實困難。讓我們來深入分析一下kruskal演算法。演算法過程不多說,直接證明 假設演算法考慮到第k條邊,這時發現邊的兩端已經在同乙個連通塊裡面了 稱為 衝突 為了使...

bzoj1016 JSOI2008 最小生成樹計數

description 現在給出了乙個簡單無向加權圖。你不滿足於求出這個圖的最小生成樹,而希望知道這個圖中有多少個不同的 最小生成樹。如果兩顆最小生成樹中至少有一條邊不同,則這兩個最小生成樹就是不同的 由於不同的最小生 成樹可能很多,所以你只需要輸出方案數對31011的模就可以了。input 第一行...

bzoj1016 JSOI2008 最小生成樹計數

現在給出了乙個簡單無向加權圖。你不滿足於求出這個圖的最小生成樹,而希望知道這個圖中有多少個不同的最小生成樹。如果兩顆最小生成樹中至少有一條邊不同,則這兩個最小生成樹就是不同的 由於不同的最小生成樹可能很多,所以你只需要輸出方案數對31011的模就可以了。第一行包含兩個數,n和m,其中1 n 100 ...