kruskal算法的套路
算法核心思想:贪心
给定一个带权图,求连通所有节点所需的最小权和
n个节点,需要连n-1条边,这些边的权值都是尽量小的,所以连最小生成树从边权最小的开始连
1:将边按照权从小到大排序(或者不排序,只要能顺利的拿到权最小的那条边就行)
2:每次选定权最小的边 连,这条边一旦导致成环就必须舍弃掉,
3:重复处理直到连了n-1条边或者所有边都考虑过了
判断成环与否使用并查集
hdu1162
#include <bits/stdc++.h> using namespace std; const int maxn=1e4; struct edge { int u,v; double w; }e[maxn]; int pre[maxn],n,m,cnt; double a[maxn],b[maxn],x,y,sum; bool cmp(edge a, edge b){return a.w<b.w;} int f(int x){return x==pre[x]?x:pre[x]=f(pre[x]);} void kruskal() { int tot=0; for(int i=0;i<m&&tot<n;i++){ int r=f(e[i].u),t=f(e[i].v); if(r!=t){ tot++;pre[r]=t;sum+=e[i].w; } } } int main() { while(scanf("%d",&n)!=EOF) { cnt=0;sum=0; for(int i=0;i<=n;i++)pre[i]=i; m=n*(n-1)/2; for(int i=0;i<n;i++) scanf("%lf%lf",&a[i],&b[i]); for(int i=0;i<n-1;i++) for(int j=i+1;j<n;j++){ x=a[i]-a[j];y=b[i]-b[j]; e[cnt].u=i;e[cnt].v=j;e[cnt].w=sqrt(x*x+y*y); cnt++; } sort(e,e+m,cmp); kruskal(); printf("%.2f\n",sum); } return 0; }
落霞与孤鹜齐飞,秋水共长天一色