HOJ 1811 最小生成树

来源:互联网 发布:js 继承 编辑:程序博客网 时间:2024/06/18 04:06

最小生成树入门题,输入n个坐标点,输出连接这些点的最小距离和。

解法1: Kruskal

//kruskal 1811#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define MAX 105using namespace std;struct Point{    double x,y;}point[MAX];struct Road{    int s,d;    double dis;}road[MAX*MAX];double dis(Point a,Point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}bool cmp(Road a,Road b){    return a.dis<b.dis;}int father[MAX];void init(){    for(int i=0;i<MAX;i++)    {        father[i]=i;    }}int find(int x){    return father[x]==x? x:father[x]=find(father[x]);}double kruskal(int index){    double min=0.0;    int a,b;    for(int i=0;i<index;i++)    {        a=find(road[i].s);        b=find(road[i].d);        if(a!=b)        {            father[a]=b;            min+=road[i].dis;        }    }    return min;}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int i,j;        memset(point,0,sizeof(point));        for(i=0;i<n;i++)        {            scanf("%lf %lf",&point[i].x,&point[i].y);        }        int index=0;        for(i=0;i<n;i++)        {            for(j=i+1;j<=n-1;j++)            {                road[index].s=i;                road[index].d=j;                road[index++].dis=dis(point[i],point[j]);            }        }        sort(road,road+index,cmp);        init();        printf("%.2lf\n",kruskal(index));    }    return 0;}

解法2: Prim

//1811 Prim#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <cmath>#define INF  0xffffffusing namespace std;struct pos{    double x,y;}f[105];double map[105][105];bool visited[105];double dist[105];double dis(pos a,pos b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int main(){    int n;    while(scanf(" %d",&n)!=EOF)    {        int i,j;        for(i=0;i<n;i++)        {            scanf("%lf %lf",&f[i].x,&f[i].y);        }        memset(map,0,sizeof(map));        memset(visited,0,sizeof(visited));        for(i=0;i<n;i++)        {            for(j=0;j<n;j++)            {                map[i][j]=dis(f[i],f[j]);            }        }    //memset(dist,100000,sizeof(dist));    //memset是按字节赋值,不要乱用。。。       for(int i=0;i<105;i++)       {           dist[i]=INF;       }        double ans=0;        dist[0]=0;        for(int i=0;i<n;i++)        {            int k=0;            double min=INF;            //找到一个能使和最小的点  将该点加入集合            for(int j=0;j<n;j++)            {                if(!visited[j] && dist[j]<min)                {                    min=dist[j];                    k=j;                }            }            ans+=min;            visited[k]=1;            //对表进行更新            for(int j=0;j<n;j++)            {                if(dist[j]>map[k][j])                {                    dist[j]=map[k][j];                }            }        }        printf("%.2lf\n",ans);    }    return 0;}


解法3: Dijkstra

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <cmath>#define INF  0xffffffusing namespace std;struct pos{    double x,y;}f[105];double map[105][105];bool visited[105];double dis(pos a,pos b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int i,j;        memset(f,0,sizeof(f));        for(i=0;i<n;i++)        {            scanf("%lf %lf",&f[i].x,&f[i].y);        }        memset(map,INF,sizeof(map));        memset(visited,0,sizeof(visited));        for(i=0;i<n-1;i++)        {            for(j=i+1;j<n;j++)            {                map[i][j]=map[j][i]=dis(f[i],f[j]);            }        }        double ans=0;        int temp;        //0为起点 找点        visited[0]=1;        for(int k=0;k<n-1;k++)        {            double s=INF;            //找到一个能使和最小的点  将该点加入集合            for(int i=1;i<n;i++)            {                if(!visited[i] && map[0][i]<s)                {                    s=map[0][i];                    temp=i;                }            }            ans+=s;            visited[temp]=1;            //对表进行更新            for(int j=1;j<n;j++)            {                if(!visited[j] && map[temp][j]<map[0][j])                {                    map[0][j]=map[temp][j];                }            }        }        printf("%.2lf\n",ans);    }    return 0;}