输入图的邻接矩阵,求最小生成树的总权值(多组数据)
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
1.prim算法:
首先从V中任取一个顶点(假定取v1),将它并入U中,此时U={v1},然后只要U是V的真子集(U∈V),就从那些一个端点已在T中,另一个端点仍在T外的所有边中,找一条最短边,设为(vi,vj),其中vi∈U,vj ∈V-U,并把该边(vi, vj)和顶点vj分别并入T的边集TE和顶点集U,如此进行下去,每次往生成树里并入一个顶点和一条边,直到n-1次后得到最小生成树。
2.关键问题: 每次如何从连接T中和T外顶点的所有边中,找到一条最短的?
2.1 如果用邻接矩阵存放图,而且选取最短边的时候遍历所有点进行选取,则总时间复杂度为O(V2), V 为顶点个数
2.2 用邻接表存放图,并使用堆来选取最短边,则总时间复杂度为O(ElogV)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
int n;
struct Edges
{
int v;
int w;
bool operator<(const Edges &e)const
{
return w>e.w;
}
Edges(int vv,int ww):v(vv),w(ww){}
Edges(){}
};
vector<vector<Edges> >g(110);//二维
int prim(vector<vector<Edges> > &g,int n)
{
Edges e(0,0);
priority_queue<Edges>q;//用优先队列,就可以取得当前权值最小的点,利于后面的判断
q.push(e);
vector<int>vis(n);
vector<int>dis(n);
for(int i=0;i<n;i++)
{
vis[i]=0;
dis[i]=inf;
}
int sum=0;//求权值之和
int cnt=0;//计数,是否联通
while(cnt<n&&!q.empty())
{
do
{
e=q.top();
q.pop();
}while(vis[e.v]==1&&!q.empty());
if(vis[e.v]==0)
{
cnt++;
vis[e.v]=1;
sum=sum+e.w;
for(int i=0;i<g[e.v].size();i++)//和e.v这个点相连的点全部扫描一遍
{
int k=g[e.v][i].v;//和e.v这个点相连的点暂存于k
if(vis[k]==0)
{
int w=g[e.v][i].w;//k对应的权值
if(dis[k]>w)
{
dis[k]=w;
q.push(Edges(k,w));
}
}
}
}
}
if(cnt<n) return -1;
return sum;
}
int main()
{
while(cin>>n)
{
for(int i=0;i<n;i++)
g[i].clear();
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
int w;
cin>>w;
g[i].push_back(Edges(j,w));
}
}
cout<<prim(g,n)<<endl;
}
return 0;
}