您的位置:首页 > 其它

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

2016-06-15 18:09 956 查看
此题为一道简单的最小生成树问题,输入一个 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
;
bool v
;
vector <int> E
,W
;
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
4000
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 最小生成树 prim