北京大学Openjudge1258:Agri-Net(最小生成树 Prim+优先队列)

1258:Agri-Net

总时间限制: 

1000ms

 

内存限制: 

65536kB

描述

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. 

输入

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.

输出

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.

样例输入

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

样例输出

28

来源

USACO 102

Source File:

先介绍第一种写法,是o(N^2)的写法

#include
#include
using namespace std;
#define MAXN 1000001
int dist[101][101];
int n;
int prim(void){
    int s=1;
    int m=1;
    bool visited[101]={false};
    visited[s]=true;

    int min_w;
    int prim_w=0;
    int point;
    int low_dis[100];

    for(int i=1;i<=n;i++)
        low_dis[i]=MAXN;
    while(true){
        if(m==n) break;
        min_w=MAXN;
        for(int i=2;i<=n;i++){

            if(!visited[i]&&low_dis[i]>dist[s][i])
                low_dis[i]=dist[s][i];
            if(!visited[i]&&min_w>low_dis[i]){
                min_w=low_dis[i];
                point=i;
            }
        }
        s=point;
        visited[s]=true;
        prim_w+=min_w;
        m++;
    }
    return prim_w;
}
int main(){
    while(cin>>n){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>dist[i][j];
            }
        }
        cout<

这一种写法其实就是用二维数组dist存储输入的数据,用visited数组表示是否访问过,并且用dis存储每次取到的最小的距离。并且用s,point表示下标,如果访问过,对应的visited数组那一项就变成true。感觉这种方法考虑的比较简单。

第二种算法,是Prim算法和优先队列结合的方法

#include 
#include
#include
#define MAXN 1<<30
using namespace std;
struct Edge{
    int v;//边端点
    int w;//边权值
    Edge(int _v=0,int _w=MAXN):v(_v),w(_w){}
    bool operator <(const Edge &e) const{
        return w>e.w;
    }

};
vector < vector  > G(110);
int Prim( const vector < vector  >&G,int n){
    Edge xDist(0,0);
    priority_queue pq;
    vector vDist(n);//存放顶点及其在建生成树的距离
    vector vUsed(n);//标记是否访问过
    int nDoneNum=0;
    for(int i=0;iw){
                        vDist[k]=w;//更新点k到在建生成树的最小距离
                        pq.push(Edge(k,w));//将距离压入队列
                    }
                }
            }
        }
    }
    if(nDoneNum>n){
        for(int i=0;i>w;
            G[i].push_back(Edge(j,w));
        }
        cout<

北京大学Openjudge1258:Agri-Net(最小生成树 Prim+优先队列)_第1张图片

 对于Prim算法,需要把握以下几点:

图节点数目为N,正在构造的生成树为T,  维护Dist数组,Dist[i]表示ViT的“距离”  开始所有Dist[i] = 无穷大, T 为空集

你可能感兴趣的:(ACM算法)