首页 > 代码库 > HDU 1863 (最小生成树之Kruskal) 畅通工程

HDU 1863 (最小生成树之Kruskal) 畅通工程

模板题,学习一下最小生成树的Kruskal算法

对于稀疏图来说

按所给的边的权值从小到大排序,如果该边不与已经选的边形成环就选择它

这里用并查集来实现

第i条边的端点放在u、v数组中,权值保存在w中

这里用的是间接排序,也就是排的是每条边的序号,放在rank数组中

 

 1 //#define LOCAL 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6  7 const int maxn = 5000; 8 int u[maxn], v[maxn], w[maxn], parent[maxn], rank[maxn]; 9 int m, n;10 11 bool cmp(const int i, const int j)12 {13     return (w[i] < w[j]);14 }15 16 int GetParent(int a)17 {18     return parent[a] == a ? a : parent[a] = GetParent(parent[a]);19 }20 21 int kruskal(void)22 {23     int cnt = 0, weight = 0;24     for(int i = 0; i < m; ++i)25     {26         int edge = rank[i];27         int x = GetParent(u[edge]);28         int y = GetParent(v[edge]);29         if(x != y)30         {31             weight += w[edge];32             ++cnt;33             parent[x] = y;34         }35     }36     if(cnt < n - 1)    weight = 0;37     return weight;38 }39 40 int main(void)41 {42     #ifdef LOCAL43         freopen("1863in.txt", "r", stdin);44     #endif45 46 47     while(scanf("%d%d", &m, &n) == 2 && m)48     {49         for(int i = 0; i < m; ++i)50             scanf("%d%d%d", &u[i], &v[i], &w[i]);51         for(int i = 0; i < n; ++i)    parent[i] = i;52         for(int i = 0; i < m; ++i)    rank[i] = i;53         sort(rank, rank + m, cmp);54         int ans = kruskal();55         if(ans)56             printf("%d\n", ans);57         else58             printf("?\n");59     }60     return 0;61 }
代码君

 

HDU 1863 (最小生成树之Kruskal) 畅通工程