算法核心思想:贪心
给定一个带权图,求连通所有节点所需的最小权和
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
",sum);
}
return 0;
}