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;
}

  

posted @ 2017-04-15 20:14  小螺号打豆豆  阅读(153)  评论(0编辑  收藏  举报