自用最小生成树模板(基于Kruskal)
2017-10-07 11:21
344 查看
200ms的板子,我尽力了,以我自己的能力没法再快了。。。
基于Kruskal的做法,跑了200ms,以我自己的能力没办法再快了,不过翻了几页评测列表发现我是最快的。。。我觉得应该会有更快的方法。
想法很简单,既然是最小生成树,把所有边按照边权升序排序,每次取一条最小权值的边,询问是否不在同一集合,如果不在,则最小生成树中就会有这条边,然后合并边所在的集合。生成树连接n个点,显然有n-1条边,所以开一个totedge来维护当前取到的边数,直到取完n-1条边为止。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define maxn 5005 #define maxm 200005 using namespace std; struct Edge{ int from,to,dis; bool operator <(const Edge &rhs)const{ return dis < rhs.dis; } }; Edge edge[maxm]; int father[maxm]; int n,m; int totedge = 0; int k = 0; int ans = 0; inline int read(){ int num = 0; char c; bool flag = false; while ((c = getchar()) == ' ' || c == '\n' || c == '\r'); if (c == '-') flag = true; else num = c - '0'; while (isdigit(c = getchar())) num = num * 10 + c - '0'; return (flag ? -1 : 1) * num; } void init(){ for (register int i=1;i<=m;i++) father[i] = i; } int find(int x){ if (father[x] == x) return father[x]; father[x] = find(father[x]); return father[x]; } void merge(int x,int y){ father[find(x)] = find(y); } int main(){ n = read();m = read(); for (register int i=1;i<=m;i++){ edge[i].from = read(); edge[i].to = read(); edge[i].dis = read(); } sort(edge+1,edge+m+1); init(); while (totedge < n-1){ if (find(edge[++k].from) != find(edge[k].to)){ ans += edge[k].dis; merge(edge[k].from,edge[k].to); totedge++; } } printf("%d\n",ans); return 0; }
相关文章推荐
- 个人模板 Kruskal 最小生成树
- 51nod 1212 无向图最小生成树(prim,kruskal模板)
- 最小生成树模板【kruskal & prim】
- 最小生成树(kruskal模版 模板)
- Kruskal(克鲁斯卡尔) 最小生成树 算法详解+模板
- 模板整理——图论·最小生成树·Kruskal
- 【模板】Kruskal 最小生成树
- 【模板】最小生成树Kruskal
- 最小生成树模板——kruskal
- 最小生成树模板(POJ 1258-prime+HDU 1233 Kruskal为例)
- 最小生成树kruskal 并查集合 模板题
- 最小生成树prim+kruskal模板
- 最小生成树-kruskal模板
- 最小生成树,POJ和HDU几道题目的解题报告(基于自己的模板)
- 最小生成树(kruskal模版 Prim模板)
- [备战NOI同步赛]Kruskal最小生成树模板
- hdu 1863 畅通工程 最小生成树模板入门题 prim+kruskal两种算法AC。
- 最小生成树 :: Prim && Kruskal 模板
- Kruskal模板求最小生成树
- 算法提高 最小方差生成树(Kruskal)_模板