码迷,mamicode.com
首页 > 其他好文 > 详细

poj 1751 highways 最小生成树

时间:2015-01-24 17:30:22      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:c++

题目链接:

1751




题意:

一个平面图中有N个城镇,标号1~N,给出这N个城镇的坐标,并给出一些已经建设好的公路,问要完成最小生成树还需要建设哪些公路。





题解 :


prim:用邻接矩阵保存所有城镇之间的距离,已建好的距离则为0;建立一个pre数组

表示当前城镇的(在最小生成树中的)前一个城镇,开始初始化为1,在更新low_distance数组时一起更新,最后pre数组保存的都是最近的城镇。最后遍历

edge[pre[i]][i],输出时去掉距离为0的即可。



kruskal:并查集时间消耗的比较大,但思路更加简洁:建边,排序,遍历所有边

如果边的两端不在一个集合且权值不为0则输出两端。

后来用到了几个优化:

1.不用计算距离 , 即 不用sqrt() 因为这道题没有要求算距离
2.已有的边直接把它们用并查集并到一块 不用什么把它们距离设为0在加进去




prim代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define maxx  9999999
double lowdis[777];
double map[777][777];
double loc[777][2];
int pre[777];
int m,n;
void  prim()
{
    int i,j,pos;
    double minn;
    for(i=1; i<=m; i++)
        lowdis[i]=map[1][i],pre[i]=1;
    lowdis[1]=-1;
    for(i=1; i<m; i++)
    {
        minn=maxx;
        for(j=1; j<=m; j++)
            if(lowdis[j]!=-1&&lowdis[j]<minn)
                minn=lowdis[j],pos=j;
        lowdis[pos]=-1;
        for(j=1; j<=m; j++)
            if(lowdis[j]>map[pos][j])
                lowdis[j]=map[pos][j],pre[j]=pos;
    }
    return;
}
int main()
{
    int t,i,j,a,b;
    scanf("%d",&m);
    for(i=1; i<=m; i++)
        scanf("%lf%lf",&loc[i][0],&loc[i][1]);
    for(i=1; i<=m; i++)
        for(j=1; j<=m; j++)
        {
            if(i==j)
                map[i][j]=maxx;
            else
                map[i][j]=map[j][i]=sqrt(pow(loc[i][0]-loc[j][0],2)+pow(loc[i][1]-loc[j][1],2));
        }
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d",&a,&b);
        map[a][b]=map[b][a]=0;
    }
    prim();
    for(i=2; i<=m; i++)
        if(map[pre[i]][i]!=0)
            cout<<pre[i]<<' '<<i<<endl;


    return 0;
}




kruskal代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
struct node
{
    int u,v,w;
} edge[777*777/2];
int fa[777];
int loc[777][2];
int m,n,s;
int cmp(node a,node b)
{
    return a.w<b.w;
}
int find(int x)
{
    int t,d=x;
    while(fa[d]>=0)
        d=fa[d];
    while(x!=d)
    {
        t=fa[x];
        fa[x]=d;
        x=t;
    }
    return d;
}
void Kruskal()
{
    int r1,r2,i,j,ss,nn=0;
    for(i=0; i<s; i++)
    {
        r1=find(edge[i].u);
        r2=find(edge[i].v);
        if(r1!=r2)
        {
            nn++;
            if(edge[i].w!=0)
            cout<<edge[i].u<<' '<<edge[i].v<<endl;
            ss=fa[r1]+fa[r2];
            if(fa[r1]<fa[r2])
                fa[r1]=ss,fa[r2]=r1;
            else
                fa[r1]=r2,fa[r2]=ss;
        }
        if(nn==m-1)
            break;
    }
    return;
}
int main()
{
    int i,j,k,a,b;
    s=0;
    scanf("%d",&m);
    memset(fa,-1,sizeof(fa));
    for(i=1; i<=m; i++)
        scanf("%d%d",&loc[i][0],&loc[i][1]);
    for(i=1; i<=m; i++)
        for(j=i+1; j<=m; j++)
        {
            edge[s].u=i,edge[s].v=j;
            edge[s++].w=(loc[i][0]-loc[j][0])*(loc[i][0]-loc[j][0])+(loc[i][1]-loc[j][1])*(loc[i][1]-loc[j][1]);
        }
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d",&a,&b);
        if(find(a)!=find(b))
            fa[find(a)]=find(b);
    }
    sort(edge,edge+s,cmp);
    Kruskal();
    return 0;
}





poj 1751 highways 最小生成树

标签:c++

原文地址:http://blog.csdn.net/axuan_k/article/details/43085667

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!