POJ 2421 Constructing Roads (最小生成树)

题意:给出邻接矩阵,在给出q条已经建好的路,让你再建一些路,使得连通所有的村庄并且兴建的路的长度时最小的。

思路:1.可以先将建好的路的端点合并,这里要注意的是,首先先要判断两个端点u、v的根节点是否相同,不同的话在合并。是为了防止有重复或者有环出现。

         2.可以将建好的路的cost设为0,再直接用kruskal算法。由于建边的时候是用了上三角矩阵,所以很容易用端点u、v来推出相应边的编号。

 

代码1:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <string>

using namespace std;

int n,q,cost,index,a,b;
int ans;

struct Edge{
    int u,v;
    int cost;

    bool operator < (const Edge& tmp) const
    {
        return cost< tmp.cost;
    }

}edge[5500];

struct UF{
    int father[110];

    void unit(){
        for(int i=1;i<=n;i++){
            father[i]=i;
        }
    }

    int find_root(int x){
        if(father[x]!=x)
            father[x]=find_root(father[x]);
        return father[x];
    }

    void Union(int fa,int fb){
        father[fb]=fa;
    }
}uf;

int main()
{
    while(scanf("%d",&n)!=EOF){
        index=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++)
                scanf("%d",&cost);
            for(int j=i+1;j<=n;j++){
                scanf("%d",&cost);
                edge[index].u=i;
                edge[index].v=j;
                edge[index].cost=cost;
                index++;
            }
        }
        sort(edge,edge+index);

        scanf("%d",&q);

        uf.unit();
        int num=0;
        for(int i=1;i<=q;i++){
            scanf("%d%d",&a,&b);
                int fa=uf.find_root(a);
                int fb=uf.find_root(b);
                //已经建好的,判断根节点是否一样,因为可能有重复,如果一样说明之前已经合并过,不一样的再合并
                //也有可能已经建好的路中会有形成环的,所以也要判断一下
                if(fa!=fb){
                    uf.Union(fa,fb);
                    num++;
                }
        }

        int count=num; //统计边数
        ans=0;
        for(int i=0;i<index;i++){
            int u=edge[i].u;
            int v=edge[i].v;
            int fu=uf.find_root(u);
            int fv=uf.find_root(v);

            if(count>=n-1){
                break;
            }

            if(fu!=fv){
                ans+=edge[i].cost;
                count++;
                uf.Union(fu,fv);

            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

代码2:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <string>

using namespace std;

int n,q,cost,index,a,b;
int ans;
int road[110][110];//road[a][b]=1表示a与b之间已经有路,防止已经建好的路中有重复

struct Edge{
    int u,v;
    int cost;

    bool operator < (const Edge& tmp) const
    {
        return cost< tmp.cost;
    }

}edge[5500];

struct UF{
    int father[110];

    void unit(){
        for(int i=1;i<=n;i++){
            father[i]=i;
        }
    }

    int find_root(int x){
        if(father[x]!=x)
            father[x]=find_root(father[x]);
        return father[x];
    }

    void Union(int fa,int fb){
        father[fb]=fa;
    }
}uf;

int main()
{
    while(scanf("%d",&n)!=EOF){
        index=0;
        memset(road,0,sizeof(road));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++)
                scanf("%d",&cost);
            for(int j=i+1;j<=n;j++){
                scanf("%d",&cost);
                edge[index].u=i;
                edge[index].v=j;
                edge[index].cost=cost;
                index++;
            }
        }
        scanf("%d",&q);
        uf.unit();
        //int num=0;
        for(int i=1;i<=q;i++){
            scanf("%d%d",&a,&b);
            //防止有重复
            if(road[a][b]==0){
                road[a][b]=1;
                road[b][a]=1;
                //额,忘记edge数组的下标是从0开始的,所以idx还要最后-1。。。
                //求出相应边的编号idx
                int idx=(2*n-a)*(a-1)/2+b-a-1;
                edge[idx].cost=0;
            }
        }

        sort(edge,edge+index);
        int count=0; //统计边数
        ans=0;
        for(int i=0;i<index;i++){
            int u=edge[i].u;
            int v=edge[i].v;
            int fu=uf.find_root(u);
            int fv=uf.find_root(v);
            if(count>=n-1){
                break;
            }

            if(fu!=fv){
                ans+=edge[i].cost;
                count++;
                uf.Union(fu,fv);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2013-10-17 09:01  辰曦~文若  阅读(206)  评论(0编辑  收藏  举报