sicily Highways prim算法与kruskal算法详解

来源:互联网 发布:gif动态制作软件 编辑:程序博客网 时间:2024/06/06 16:29

一、题目 1090. Highways

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public highways. So the traffic is difficult in Flatopia. The Flatopian government is aware of this problem. They’re planning to build some highways so that it will be possible to drive between any pair of towns without leaving the highway system.

Flatopian towns are numbered from 1 to N. Each highway connects exactly two towns. All highways follow straight lines. All highways can be used in both directions. Highways can freely cross each other, but a driver can only switch between 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 to be built. However, they want to guarantee that every town is highway-reachable from every other town.

Input

The first line is an integer N (3 <= N <= 500), which is the number 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 an integer within [1, 65536]) between village i and village j.

Output

You should output a line contains an integer, which is the length of the longest road to be built such that all the villages are connected, and this value is minimum.
This problem contains multiple test cases!
The first line of a multiple input is an integer T, then a blank line followed by T input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
The output format consists of T output blocks. There is a blank line between output blocks.

Sample Input

130 990 692990 0 179692 179 0

Sample Output

692

二、思考与总结

1、这是一个最小生成树的问题,可以用kruskal算法和prim算法去解决问题。
2、太坑了不知道为何不给我用qsort,后来换成了sort才行,好奇怪。

三、prim算法

算法参考:最小生成树Prim算法理解

代码

#include <iostream>const int MAXN = 550;const int MAX_INT = 2147483647;using namespace std;int prim(int map[MAXN][MAXN], int N) {    int lowCost[MAXN], startOfLowCost[MAXN];    int longestRoad = 0;    lowCost[0] = 0;    //  lowCost[i] = 0 and startOfLowcost = 0 means vertex i is a root of the mst    //  init    for (int i = 1; i < N; i++) {        lowCost[i] = map[0][i];        startOfLowCost[i] = 0;    }    for (int i = 1; i < N; i++) {        int min = MAX_INT;        int minid = 0;        //  find the min road;        for (int j = 1; j < N; j++) {            if (lowCost[j] != 0 && lowCost[j] < min) {                min = lowCost[j];                minid = j;            }        }        if (min > longestRoad) longestRoad = min;        lowCost[minid] = 0; //  became root        for (int j = 1; j < N; j++) {            if (map[minid][j] < lowCost[j]) {                lowCost[j] = map[minid][j];                startOfLowCost[j] = minid;            }        }    }    return longestRoad;}int main(int argc, const char * argv[]) {    int T, N;    cin >> T;    int map[550][550];    while (T--) {        cin >> N;        for (int i = 0; i < N; i++) {            for (int j = 0; j < N; j++) {                cin >> map[i][j];            }        }        cout << prim(map, N) << endl;        if (T) cout << endl;    }}

四、kruskal算法

参考文章:Prim算法和Kruskal算法

其实个人觉得kruskal算法比prim算法实现起来更简单
kruskal算法的基本思路就是
1、将所有边加入到一个存放边的容器中(代码中因为图是无向图,所以我们只把上三角加入即可)
2、按从小到大给边排序
3、初始化所有边,另所有边各属于不同的集合
4、每次取一条边,若这边连接的两个顶点不相同且属于不同的集合,则把这连个顶点放到同一个集合中,getfFather函数带点并查集的思想。重复直到所有边属于同一集合即可,最坏情况执行 总边数 次。

////  main.cpp//  Highways////  Created by 邱兆丰 on 17/12/2016.//  Copyright © 2016 菇生. All rights reserved.//#include <iostream>#include <memory.h>#include <algorithm>const int MAXN = 550;const int MAX_INT = 2147483647 / 2;const int MAX_EDGE = 130000;using namespace std;typedef struct node{    int u;                                                 //边的起始顶点    int v;                                                 //边的终止顶点    int w;                                                 //边的权值}Edge;bool compare(Edge a, Edge b) {    return a.w < b.w;}int getFather(int x, int* vertexSet) {    return vertexSet[x] == x ? x : vertexSet[x] = getFather(vertexSet[x], vertexSet);}int kruskal(int map[MAXN][MAXN], int N) {    int longestRoad = 0;    int vertexSet[MAXN];   //  顶点属于的集合    Edge E[MAX_EDGE];           //存放所有的边    for (int i = 0; i < N; i++) {   //一开始各属各集,n个顶点有n个集合        vertexSet[i] = i;    }    int vertexNum = 0;    for (int i = 0; i < N - 1; i++) {        for (int j = i + 1; j < N; j++) {            if (map[i][j] != 0 && map[i][j] != MAX_INT) {                E[vertexNum].u = i;                E[vertexNum].v = j;                E[vertexNum++].w = map[i][j];            }        }    }    sort(E, E + vertexNum, compare);    for (int i = 0; i < vertexNum; i++) {        int set1 = getFather(E[i].u, vertexSet);        int set2 = getFather(E[i].v, vertexSet);        if (set1 != set2) {            if (E[i].w > longestRoad) longestRoad = E[i].w;            vertexSet[set1] = set2;        }    }    return longestRoad;}int main(int argc, const char * argv[]) {    int T, N;    cin >> T;    int map[550][550];    while (T--) {        cin >> N;        for (int i = 0; i < N; i++) {            for (int j = 0; j < N; j++) {                cin >> map[i][j];            }        }        cout << kruskal(map, N) << endl;        if (T) cout << endl;    }}
0 0
原创粉丝点击