poj 1258(最小生成樹 Kruskal)

Agri-Net
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 26390   Accepted: 10410

Description

Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He needs your help, of course. 
Farmer John ordered a high speed connection for his farm and is going to share his connectivity with the other farmers. To minimize cost, he wants to lay the minimum amount of optical fiber to connect his farm to all the other farms. 
Given a list of how much fiber it takes to connect each pair of farms, you must find the minimum amount of fiber needed to connect them all together. Each farm must connect to some other farm such that a packet can flow from any one farm to any other farm. 
The distance between any two farms will not exceed 100,000. 

Input

The input includes several cases. For each case, the first line contains the number of farms, N (3 <= N <= 100). The following lines contain the N x N conectivity matrix, where each element shows the distance from on farm to another. Logically, they are N lines of N space-separated integers. Physically, they are limited in length to 80 characters, so some lines continue onto others. Of course, the diagonal will be 0, since the distance from farm i to itself is not interesting for this problem.

Output

For each case, output a single integer length that is the sum of the minimum length of fiber required to connect the entire set of farms.

Sample Input

4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0

Sample Output

28

Source




題目類型:最小生成樹

題目描述:略

題目分析:把N個節點連接到一起,要求權值最小。這樣的問題,就屬於最小生成樹的問題。

相當於,在無向連通圖中,找一無迴路子圖,這個子圖連接了所有的定點,並且所用權值最小。

因爲是無迴路圖且連接了所有定點,所以肯定是樹,稱爲生成樹,因爲權值最小,所以稱最小生成樹。

最小生成樹算法的思想是,維護一個邊集A,A爲圖G某最小生成樹邊集的子集。
然後,往A中加入安全邊直到,A爲圖G的某個最小生成樹。
如果把邊(u,v)加入到A中, A仍然能保持原來的性質(爲某最小生成樹邊集的子集),那麼就稱(u,v)爲安全邊。

對於Kruskal算法來說,他是這麼選擇安全邊的。

(1) 把每個頂點作爲一個集合。
(2) 把圖中的邊按升序排序。
(3) 遍歷圖中的邊(u,v),如果u和v不在一個集合裏。此時(u,v)爲安全邊。把u,v所在集合合併,把(u,v)加入到A中。


代碼如下:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#define V 101
#define E V * (V-1) / 2
using namespace std;

struct Edge{
    int u;
    int v;
    int w;
};
Edge edge[E];
int f[V];
int rank[V];
int n;

bool cmp(Edge a,Edge b){
    if( a.w < b.w) {
        return true;
    } else {
        return false;
    }
}

void makeSet(){
    for(int i = 0; i < n; i++){
        f[i] = i;
        rank[i] = 0;
    }
}
int findRoot(int x){
    if(x == f[x]){
        return x;
    } else {
        return f[x] = findRoot(f[x]);
    }
}
void merge(int a,int b){
    int ra = findRoot(a);
    int rb = findRoot(b);
    if(ra != rb) {
        if(rank[ra] < rank[rb]){
            f[ra] = rb;
        } else {
            f[rb] = ra;
            if(rank[ra] == rank[rb]){
                rank[ra]++;
            }
        }
    }
}




int main()
{
    while(scanf("%d",&n) != EOF){
        int sum = 0;
        int k = -1;
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                int w;
                scanf("%d",&w);
                if( j > i){
                    k++;
                    edge[k].u = i;
                    edge[k].v = j;
                    edge[k].w = w;
                }
            }
        }

        //Kruskal
        makeSet();
        sort(edge,edge+k+1,cmp);
        for(int i = 0; i <= k; i++){
            int ru = findRoot(edge[i].u);
            int rv = findRoot(edge[i].v);
            if(ru != rv) {
                sum += edge[i].w;
                merge(edge[i].u,edge[i].v);
            }
        }
        printf("%d\n",sum);
    }

    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章