N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。
Input
第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000) 第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
Output
输出最小生成树的所有边的权值之和。
Input示例
9 14 1 2 4 2 3 8 3 4 7 4 5 9 5 6 10 6 7 2 7 8 1 8 9 7 2 8 11 3 9 2 7 9 6 3 6 4 4 6 14 1 8 8
Output示例
37
//program 2-6
#include <iostream>
using namespace std;
const int INF = 0x3fffffff;
const int N = 1005;
bool s[N];
int closest[N];
int lowcost[N];
void Prim(int n, int u0, int c[N][N])
{ //顶点个数n、开始顶点u0、带权邻接矩阵C[n][n]
//如果s[i]=true,说明顶点i已加入最小生成树
//的顶点集合U;否则顶点i属于集合V-U
//将最后的相关的最小权值传递到数组lowcost
s[u0]=true; //初始时,集合中U只有一个元素,即顶点u0
int i;
int j;
for(i=1; i<=n; i++)
{
if(i!=u0)
{
lowcost[i]=c[u0][i];
closest[i]=u0;
s[i]=false;
}
else
lowcost[i]=0;
}
for(i=1; i<=n;i++) //在集合中V-u中寻找距离集合U最近的顶点t
{
int temp=INF;
int t=u0;
for(j=1;j<=n;j++)
{
if((!s[j])&&(lowcost[j]<temp))
{
t=j;
temp=lowcost[j];
}
}
if(t==u0)
break; //找不到t,跳出循环
s[t]=true; //否则,讲t加入集合U
for(j=1; j<=n;j++) //更新lowcost和closest
{
if((!s[j])&&(c[t][j]<lowcost[j]))
{
lowcost[j]=c[t][j];
closest[j]=t;
}
}
}
}
int main()
{
int n, c[N][N], m, u, v, w;
int u0;
//cout<<"输入结点数n和边数m:"<<endl;
cin>>n>>m;
int sumcost=0;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
c[i][j]=INF;
//cout <<"输入结点数u,v和边值w:"<<endl;
for(int i=1; i<=m; i++)
{
cin>>u>>v>>w;
c[u][v]=c[v][u]=w;
}
//cout <<"输入任一结点u0:"<<endl;
//cin >> u0 ;
//计算最后的lowcos的总和,即为最后要求的最小的费用之和
u0=1;
Prim(n, u0, c);
//cout <<"数组lowcost的内容为"<<endl;
//for(int i = 1; i <= n; i++)
//cout << lowcost[i] << " ";
//cout << endl;
for(int i = 1; i <= n; i++)
sumcost += lowcost[i];
cout <<sumcost<<endl;
return 0;
}