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

来源:互联网 发布:如何防范网络恐怖 编辑:程序博客网 时间:2024/06/10 01:30

此题为一道简单的最小生成树问题,输入一个 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