POJ 1258 Agri-Net 最小生成树 Prim 算法

Prim 算法描述

1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:V new = {x},其中x为集合V中的任一节点(起始点),E new = {},为空;
3).重复下列操作,直到V new = V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合V new中的元素,而v不在V new 集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合V new中,将<u, v>边加入集合E new中;
4).输出:使用集合V new和E new来描述所得到的 最小生成树。
图例 说明 不可选 可选 已选(Vnew
POJ 1258 Agri-Net 最小生成树 Prim 算法_第1张图片
此为原始的加权连通图。每条边一侧的数字代表其权值。 - - -
POJ 1258 Agri-Net 最小生成树 Prim 算法_第2张图片
顶点D被任意选为起始点。顶点ABEF通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。 C, G A, B, E, F D
POJ 1258 Agri-Net 最小生成树 Prim 算法_第3张图片
下一个顶点为距离DA最近的顶点。BD为9,距A为7,E为15,F为6。因此,FDA最近,因此将顶点F与相应边DF以高亮表示。 C, G B, E, F A, D
POJ 1258 Agri-Net 最小生成树 Prim 算法_第4张图片
算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。 C B, E, G A, D, F
POJ 1258 Agri-Net 最小生成树 Prim 算法_第5张图片
在当前情况下,可以在 CEG间进行选择。 CB为8, EB为7, GF为11。点 E最近,因此将顶点 E与相应边 BE高亮表示。
C, E, G A, D, F, B
POJ 1258 Agri-Net 最小生成树 Prim 算法_第6张图片
这里,可供选择的顶点只有CGCE为5,GE为9,故选取C,并与边EC一同高亮表示。 C, G A, D, F, B, E
POJ 1258 Agri-Net 最小生成树 Prim 算法_第7张图片
顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG G A, D, F, B, E, C
POJ 1258 Agri-Net 最小生成树 Prim 算法_第8张图片
现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。 A, D, F, B, E, C, G
Prim算法的效率取决于结点数|v|,所以一般试用于稠密图。

Agri-Net
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 46318   Accepted: 19051

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

USACO 102

[Submit]   [Go Back]   [Status]   [Discuss]

Home Page   Go Back  To top

裸最小生成树

//感谢bin巨的模板

ACcode:

#pragma warning(disable:4786)//使命名长度不受限制
#pragma comment(linker, "/STACK:102400000,102400000")//手工开栈
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <stack>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define rds(x) scanf("%s",x)
#define rdc(x) scanf("%c",&x)
#define ll long long int
#define maxn 105
#define mod 1000000007
#define INF 0x3f3f3f3f //int 最大值
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define MT(x,i) memset(x,i,sizeof(x))
#define PI  acos(-1.0)
#define E  exp(1)
using namespace std;
bool vis[maxn];
int lowc[maxn];
int a[maxn][maxn];
int Prim(int cost[][maxn],int n){///点是1~n
    int ans=0;
    MT(vis,false);
    vis[0]=true;
    FOR(i,1,n-1)lowc[i]=cost[0][i];
    FOR(i,1,n-1){
        int minc=INF;
        int p=-1;
        FOR(j,0,n-1)
            if(!vis[j]&&minc>lowc[j]){
                minc=lowc[j];
                p=j;
            }
           if(minc==INF)return -1;///原图不连接
            ans+=minc;
            vis[p]=true;
            FOR(j,0,n-1)
                if(!vis[j]&&lowc[j]>cost[p][j])
                        lowc[j]=cost[p][j];
    }
    return ans;
}
int main(){
    int n;
    while(rd(n)!=EOF){
        FOR(i,0,n-1)
            FOR(j,0,n-1)
                rd(a[i][j]);
        printf("%d\n",Prim(a,n));
    }
    return 0;
}
/*
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
*/


你可能感兴趣的:(C++,最小生成树,poj,Prim)