1. 程式人生 > >[ACM] poj 1258 Agri-Net (最小生成樹)

[ACM] poj 1258 Agri-Net (最小生成樹)

call pack 地圖 rest width none minimum logic 最小值

版權聲明:本文為博主原創文章,未經博主同意不得轉載。 https://blog.csdn.net/sr19930829/article/details/27087575

Agri-Net
Time Limit:?1000MS ? Memory Limit:?10000K
Total Submissions:?37131 ? Accepted:?14998

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


代碼:

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn=5010;
int parent[110];
int n;

struct Node
{
    int from,to,edge;
}node[maxn];

void init(int n)
{
    for(int i=1;i<=n;i++)
        parent[i]=i;
}

int find(int x)
{
    return parent[x]==x?x:find(parent[x]);
}

bool cmp(Node a,Node b)
{
    if(a.edge<b.edge)
        return true;
    return false;
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        int m=1;
        int len;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&len);
                if(i<j)
                {
                    int temp=m;
                    node[temp].from=i;
                    node[temp].to=j;
                    node[temp].edge=len;
                    m++;
                }
            }
        init(n);
        m=n*(n-1)/2;
        len=0;
        sort(node+1,node+1+m,cmp);
        for(int i=1;i<=m;i++)
        {
            int x=find(node[i].from);
            int y=find(node[i].to);
            if(x==y)
                continue;
            else
            {
                len+=node[i].edge;
                parent[x]=y;
            }
        }
        printf("%d\n",len);
    }
    return 0;
}

prim算法:

技術分享圖片


代碼:

#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
const int maxn=110;
const int inf=0x7fffffff;
int map[maxn][maxn],low[maxn],visit[maxn];
//map數組用來記錄地圖。low數組用來保存與已增加樹中的頂點相連的邊,(保證權值最小的肯定在裏邊),visit用來記錄該頂點是否已增加樹中
int n;

int prim()
{
    int pos,Min,result=0;
    memset(visit,0,sizeof(visit));
    visit[1]=1,pos=1;//首先找的是1這個頂點。增加圖中
    for(int i=1;i<=n;i++)
        if(i!=pos)
        low[i]=map[pos][i];//與1頂點相連的邊地權值
    for(int i=1;i<n;i++)//每次增加一條邊,n個頂點增加n-1條邊,循環n-1次就能夠了
    {
        Min=inf;
        for(int j=1;j<=n;j++)
            if(!visit[j]&&Min>low[j])
            {
                Min=low[j];//Min找到的是與已增加圖中的頂點相連的邊的最小值
                pos=j;//該頂點為j
            }
        result+=Min;//加上最小邊
        visit[pos]=1;//新的頂點位置
        for(int j=1;j<=n;j++)
            if(!visit[j]&&low[j]>map[pos][j])
            low[j]=map[pos][j];//更新low[]值,新的與圖中已有的點相連的邊。假設比原來小的,就更新
    }
    return result;
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&map[i][j]);
                map[j][i]=map[i][j];
            }
        //對於題目中輸入了map[i][i]的值的話,map數組不用預處理。假設沒輸入,那麽memset(map,0x3f3f3f3f,sizeof(map));最大化處理
        cout<<prim()<<endl;
    }
    return 0;
}


[ACM] poj 1258 Agri-Net (最小生成樹)