POJ_1258_Agri-Net(USACO 102)_最小生成树

13 篇文章 0 订阅
9 篇文章 0 订阅

此题为一道简单的最小生成树问题,输入一个 n*n 的邻接矩阵,然后在图上找最小生成树即可。

我用Prim算法解的此题,算法思路也很简单,就是贪心。首先先随便把一个点加入到树中,然后不断地由此扩展其他的点,加边的过程就是贪心,即每次加入树的边都是当前与树上节点相连的边中最短的边。

算法的证明也很简单,就是反证法,很好证明,引用他人证明:

简单证明prim算法
反证法:假设prim生成的不是最小生成树
1).设prim生成的树为G0
2).假设存在Gmin使得cost(Gmin)小于cost(G0),则在Gmin中存在 < u,v >不属于G0
3).将 < u,v > 加入G0中可得一个环,且 < u,v > 不是该环的最长边(这是因为 < u,v > ∈Gmin)
4).这与prim每次生成最短边矛盾
5).故假设不成立,命题得证
详解:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int N=1050;
int n,a,sum,d[N];
bool v[N];
vector <int> E[N],W[N];
int prim()
{
    sum=0;
    memset (d,0x3f,sizeof(d));
    v[1]=true;
    for (int i=0;i<E[1].size();i++)
    {
        int v=E[1][i];
        int w=W[1][i];
        if(w<d[v])
            d[v]=w;
    }
    for (int i=1;i<=n-1;i++)
    {
        int minid=-1,minw=0x3f3f3f3f;
        for (int j=1;j<=n;j++)
        {
            if (v[j]==true) continue;
            if (d[j]<minw)
            {
                minw=d[j];
                minid=j;
            }
        }
        if (minid==-1)
            return 2147483640;
        v[minid]=true;
        sum+=minw;
        for (int j=0;j<E[minid].size();j++)
        {
            int v=E[minid][j],w=W[minid][j];
            if(d[v]>w)
                d[v]=w;
        }
    }
    return sum;
}

int main()
{
    while (cin>>n)
    {
        memset (v,false,sizeof(v));
        for (int i=1;i<=n;i++)
        {
            E[i].clear();
            W[i].clear();
        }
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            {
                scanf ("%d",&a);
                if(a!=0)
                {
                    E[i].push_back(j);
                    W[i].push_back(a);
                }
            }
        printf ("%d\n",prim());
    }   
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值