zoukankan      html  css  js  c++  java
  • POJ 2485 Highways( 最小生成树)

    题目链接

    Description
    The islandnation of Flatopia is perfectly flat. Unfortunately, Flatopia has no publichighways. So the traffic is difficult in Flatopia. The Flatopian government isaware of this problem. They're planning to build some highways so that it willbe possible to drive between any pair of towns without leaving the highwaysystem.

    Flatopian towns are numbered from 1 to N. Each highway connects exactly twotowns. All highways follow straight lines. All highways can be used in bothdirections. Highways can freely cross each other, but a driver can only switchbetween highways at a town that is located at the end of both highways.

    The Flatopian government wants to minimize the length of the longest highway tobe built. However, they want to guarantee that every town is highway-reachablefrom every other town.

    Input
    The firstline of input is an integer T, which tells how many test cases followed.
    The first line of each case is an integer N (3 <= N <= 500), which is thenumber of villages. Then come N lines, the i-th of which contains N integers,and the j-th of these N integers is the distance (the distance should be aninteger within [1, 65536]) between village i and village j. There is an emptyline after each test case.

    Output
    For eachtest case, you should output a line contains an integer, which is the length ofthe longest road to be built such that all the villages are connected, and thisvalue is minimum.

    Sample Input
    1
    3
    0 990 692
    990 0 179
    692 179 0

    Sample Output
    692

    分析:
    最小生成树问题,但不是求边的权值之和,而是求最小生成树中最长的那条边的长度。用Prim算法和Kruskal算法均可以。由于题目的测试数据是以邻接矩阵的形式给出的,因此可以考虑优先使用Prim算法。如果使用Kruskal算法,还需要把邻接矩阵中的顶点和边分离出来。

    prim代码:

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    int n;
    int tu[505][505];
    int dis[505],vis[505];
    void prim()
    {
        for(int i=1;i<=n;i++)//初始化,所有点的距离以及是否访问过
        {
            dis[i]=tu[1][i];
            vis[i]=0;
        }
        vis[1]=1;//标记1号顶点已经访问过
        int Min;
        int k;
        int ans=0;//保存最小生成树里面的最大边
        //int sun=0;//最小生成树的值
        for(int i=1;i<n;i++)
        {
            Min=0x3f3f3f3f;
            for(int j=1;j<=n;j++)
            {
                if(vis[j]==0&&Min>dis[j])
                {
                    Min=dis[j];
                    k=j;
                }
            }
            if(ans<dis[k])
                ans=dis[k];
            vis[k]=1;//标记k这个点已经访问过
            //sum+=dis[k];
            for(int j=1;j<=n;j++)
            {
                if(vis[j]==0&&dis[j]>tu[k][j])
                    dis[j]=tu[k][j];
            }
        }
        printf("%d
    ",ans);
        //printf("%d
    ",sum);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                scanf("%d",&tu[i][j]);
            prim();
        }
    }
    

    Kruskal算法:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n;
    int Count;
    int tu[505][505];
    int Tree[505];//并查集的数组
    struct Node
    {
        int a,b,w;
    } node[505*505];
    bool cmp(Node A,Node B)
    {
        if(A.w!=B.w)
            return A.w<B.w;
        if(A.a!=B.a)
            return A.a<B.a;
        return A.b<B.b;
    }
    
    int findRoot(int x)           //递归查找顶点x所在树的根
    {
        if (Tree[x] == x) return x;//若为x,则x的根就是自身
        else                    //否则
        {
            int tmp =findRoot(Tree[x]);//递归查找x的父亲Tree[x]的根,tmp为最终的树根
            Tree[x]= tmp;           //查找过程中进行路径压缩:把x到根之间遇到的所有顶点的父亲设为tmp
            return tmp;             //返回树根
        }
    }
    
    void Kruskal()
    {
        int ans=0;
        int k=0;
        int sum=0;
        for(int i=0; i<Count; i++)//遍历排序好的每一条边
        {
            if(k==n-1) break;//如果当前的生成树中已经有了n-1条边,就不用在接着往下找了
            int a=findRoot(node[i].a);
            int b=findRoot(node[i].b);
            if(a!=b)
            {
                k++;
                Tree[a]=b;
                //sum+=node[i].w;
                if(ans<node[i].w)
                    ans=node[i].w;
            }
        }
        printf("%d
    ",ans);
        //printf("%d
    ",sum);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++)
                {
                    scanf("%d",&tu[i][j]);
                }
            for(int i=1; i<=n; i++)
                Tree[i]=i;//标记没一个点都是只属于自身的集合
            Count=0;
            for(int i=1; i<=n; i++)
                for(int j=1; j<i; j++)
                {
                    node[Count].a=i;
                    node[Count].b=j;
                    node[Count].w=tu[i][j];
                    Count++;
                }
            sort(node,node+Count,cmp);
            Kruskal();
        }
        return 0;
    }
    
  • 相关阅读:
    资源利用率提高67%,腾讯实时风控平台云原生容器化之路
    热门分享预告|腾讯大规模云原生平台稳定性实践
    Fluid + GooseFS 助力云原生数据编排与加速快速落地
    基于 Clusternet 与 OCM 打造新一代开放的多集群管理平台
    案例 | 沃尔玛 x 腾讯云 Serverless 应用实践,全力保障消费者购物体验
    SuperEdge 高可用云边隧道有哪些特点?
    kubernetes 降本增效标准指南|ProphetPilot:容器智能成本管理引擎
    公有云上构建云原生 AI 平台的探索与实践
    如何削减 50% 机器预算?“人机对抗”探索云端之路
    SuperEdge 易学易用系列-SuperEdge 简介
  • 原文地址:https://www.cnblogs.com/cmmdc/p/7709319.html
Copyright © 2011-2022 走看看