最小生成树之Prim

A:生成树

B:未被访问过的点的集合

pre[i]:生成树中i的前驱节点。

A中的dis[i]:生成树中包含点i的边的长度。

B中的dis[i]: i到A的最短距离

vis[]:标记是否遍历过(是否属于A)

 

Prim算法的思想

1.任选一点,不妨选择第一个点,加入生成树A。

2.遍历B,寻找一点u,使其到A的距离最小(就是A中也找了一点v)。添加u到A中(vis)。记录这条边及其权值(pre,dis)。

3.更新与u相连的点的dis和pre

4.循环直到遍历所有可达的点。

View Code
#include <iostream>
#include <climits> 
using namespace std;

#define Max 100
void Prim(int n, int map[Max][Max], int dis[Max], int pre[Max])
{
    bool visit[Max];
    
    //初始化 
    for (int i = 2; i <= n; ++i)
    {
        visit[i] = false;
        
        dis[i] = map[1][i];
        
        pre[i] = 1;
    }
    
    visit[1] = true;
    
    dis[1] = 0;
    
    //循环n-1次,每次加入一个点 
    for (int i = 1; i < n; ++i)
    {
        int min = INT_MAX;
        
        int next = 0;
        
        //找到最小边 
        for (int j = 2; j <= n; ++j) 
        {
            if (!visit[j] && dis[j] < min)
            {
                min = dis[j];
                
                next = j;
            }
        }
        
        //找不到 
        if (next == 0)return;
        
        //加入生成树
        visit[next] = true;
        
        //更新与k相邻的顶点。
        for (int j = 2; j <= n; j++)
        {
            if (!visit[j] && map[j][next] < INT_MAX && dis[j] > map[j][next])
            {
                dis[j] = map[j][next];
                
                pre[j] = next;
            }
        }
    }
}

 

基本的最小生成树题目。

View Code
/*
【题目来源】 
http://soj.me/1090
最小生成树。
【题目分析】
给定邻接矩阵,求最小生成树的最长边。
【思路分析】
prim算法。 
*/
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <climits>
using namespace std;

#define Max 502

int map[Max][Max], dis[Max], pre[Max];

bool Prim(int n)
{
    bool vis[Max];
    
    //初始化 
    for (int i = 2; i <= n; ++i)
    {
        dis[i] = map[1][i];
        
        vis[i] = false;
        
        pre[i] = 1;
    }
    
    vis[1] = true;
    
    dis[1] = 0;
    
    //循环n-1次 
    for (int i = 1; i < n; ++i)
    {
        int min = INT_MAX;
        
        int k = 0;
        
        //找到最小边 
        for (int j = 2; j <= n; ++j)
        {
            if (min > dis[j] && !vis[j])
            {
                min = dis[j];
                
                k = j;
            }
        }
        
        //找不到 
        if (k == 0)    return false;
        
        //加入生成树 
        vis[k] = true;
        
        //更新其他各点 
        for (int j = 1; j <= n; ++j)
        {
            if (!vis[j] && map[k][j] < dis[j] && map[j][k] != INT_MAX)
            {
                dis[j] = map[k][j];
                
                pre[j] = k;
            }
        }
    }
}


int main()
{
    int n;
    
    int m;
    
    cin >> m;
    
    int m2 = m;
    
    while (m--)
    {
        if  (m != m2-1) cout << endl;
        
        cin >> n;
        
        memset(dis, 0, sizeof(dis));
        
        for (int i = 1; i <= n; ++i)
        {
            for (int j = 1; j <= n; ++j)
            {
                cin >> map[i][j];
            }
        }
        
        Prim(n);
        
        cout << *max_element(dis, dis+n+1) << endl;
    }
    
}

 

posted @ 2013-02-07 10:29  Norcy  阅读(288)  评论(0编辑  收藏  举报