POJ-1258 Agri-Net 最小生成树(MST)

来源:互联网 发布:超星泛雅网络课程 编辑:程序博客网 时间:2024/05/19 18:42

Agri-Net
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 51285 Accepted: 21378

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

40 4 9 214 0 8 179 8 0 1621 17 16 0

Sample Output

28
题目大意:输入图的邻接矩阵,求最小生成树的总权值(多组数据)

此处引用两个用容器写的Kruskal 和 Prim(堆优化)的模板,自己对容器的运用还是不熟,以后尽量用容器写吧,特别是堆优化的必须用STL

Prim算法(堆优化)代码:

//by Guo Wei/*输入图的邻接矩阵,求最小生成树的总权值(多组数据) 时间复杂度:O(ElogV) 或 O(VlogV+E)(斐波那契堆)适用于密集图*/ #include <iostream>#include <vector>#include <algorithm>#include <queue>using namespace std;const int  INFINITE = 1 << 30;struct Edge{    int v; //边端点,另一端点已知    int w; //边权值,也用来表示v到在建最小生成树的距离    Edge(int v_ = 0, int w_ = INFINITE):v(v_),w(w_) { }    bool operator <(const Edge & e) const    {        return w > e.w;  //在队列里,边权值越小越优先    }};vector< vector <Edge> > G(110); //图的邻接表int HeapPrim(const vector<vector<Edge> > & G, int n)//G是邻接表,n是顶点数目,返回值是最小生成树权值和{    int i,j,k;    Edge xDist(0,0);    priority_queue<Edge> pq; //存放顶点及其到在建生成树的距离    vector<int> vDist(n); //各顶点到已经建好的那部分树的距离    vector<int> vUsed(n);//标记顶点是否已经被加入最小生成树    int nDoneNum = 0; //已经被加入最小生成树的顶点数目    for( i = 0;i < n;i ++ )    {        vUsed[i] = 0;        vDist[i] = INFINITE;    }    nDoneNum = 0;    int nTotalW = 0; //最小生成树总权值    pq.push(Edge(0,0)); //开始只有顶点0,它到最小生成树距离0    while(nDoneNum < n && !pq.empty())    {        do {//每次从队列里面拿离在建生成树最近的点            xDist = pq.top();            pq.pop();        }while( vUsed[xDist.v] == 1 && ! pq.empty());        if( vUsed[xDist.v] == 0 )        {            nTotalW += xDist.w; vUsed[xDist.v] = 1; nDoneNum ++;            for( i = 0;i < G[xDist.v].size();i ++ )            {//更新新加入点的邻点                int k = G[xDist.v][i].v;                if( vUsed[k] == 0)                {                    int w = G[xDist.v][i].w ;                    if( vDist[k] > w )                    {                        vDist[k] = w;                        pq.push(Edge(k,w));                    }                }            }        }    }    if( nDoneNum < n )        return -1; //图不连通    return nTotalW;}int main(){    int N;    while(cin >> N)    {        for( int i = 0;i < N; ++i)            G[i].clear();        for( int i = 0; i < N; ++i)        for( int j = 0; j < N; ++j)        {            int w;            cin >> w;            G[i].push_back(Edge(j,w));        }        cout << HeapPrim(G,N) << endl;    }}

Kruskal算法:

//by Guo Wei/*时间复杂度:O(ElogE)适用于稀疏图*/#include <iostream>#include <vector>#include <algorithm>using namespace std;struct Edge{    int s,e,w; //起点,终点,权值    Edge(int ss,int ee,int ww):s(ss),e(ee),w(ww) { }    Edge() { }    bool operator < (const Edge & e1) const    {    return w < e1.w;    }};vector <Edge> edges;vector <int> parent;int GetRoot(int a){    if( parent[a] == a)    return a;    parent[a] = GetRoot(parent[a]);    return parent[a];}void Merge(int a,int b){    int p1 = GetRoot(a);    int p2 = GetRoot(b);    if( p1 == p2)    return;    parent[p2] = p1;}int main(){    int N;    while(cin >> N)    {        parent.clear();   edges.clear();        for( int i = 0;i < N; ++i)            parent.push_back(i);        for( int i = 0; i < N; ++i)        for( int j = 0; j < N; ++j)        {            int w;            cin  >> w;            edges.push_back(Edge(i,j,w));        }        sort(edges.begin(),edges.end());        int done = 0;  int totalLen = 0;        for( int i = 0;i < edges.size(); ++i)        {            if( GetRoot(edges[i].s) != GetRoot(edges[i].e))            {                Merge(edges[i].s,edges[i].e);                ++done;                totalLen += edges[i].w;            }            if( done == N – 1)                break;        }            cout << totalLen << endl;    }}


0 0
原创粉丝点击