这里的思路就是先用prim算法求的最小生成树,然后在prim算法中添加一个MAX数组,用MAX数组存放两点间的最大距离,并且用一个use数组(布尔类型)存放是否使用过该边,最后再在没有使用的变进行遍历,找出最小,求的最小生成树!
引用:
下面介绍一下利用prim求次小生成树的主要步骤。
1.先求出来最小生成树。并将最小生成树任意两点之间路径当中的权值最大的那一条找出来,为什么要找最大的呢,因为生成树加入一条边之后一定构成了回路,那么肯定要去掉这个回路当中一条边才是生成树,那么,怎么去边才是次小的,那就去掉除了刚刚添加的一条边之外回路当中权值最大的一个,所以留下的就是最小的。
2.枚举最小生成树外的每一条边。找出最小的就是次小生成树。
const int MAXN = 110;
const int INF = 0x3f3f3f3f;
bool vis[MAXN];
int low[MAXN];
int pre[MAXN];
int MAX[MAXN][MAXN];
bool used[MAXN][MAXN];
int cost[MAXN][MAXN];
int Prime(int n){
int ans=0;
memset(vis,false,sizeof vis);
memset(low,0,sizeof low);
memset (MAX,0,sizeof MAX);
memset(used,false,sizeof used);
memset(low ,0 ,sizeof low);
pre[0]=-1;
vis[0]=true;
low[0]=0;
for(int i=0;i<n;i++)
low[i]=cost[0][i];
for(int i=1;i<n;i++){
int minc=INF;
int p=-1;
for(int j=1;j<n;j++){
if(!vis[j]&&minc>low[j]){
p=j;
minc=j;
}
}
if(p==-1)
return -1;
ans+=minc;
vis[p]=true;
used[pre[p]][p]=used[p][pre[p]]=true;
for(int j=1;j<n;j++){
if(vis[j])
MAX[j][p]=MAX[p][j]=max(MAX[j][pre[p]],low[p]);
if(!vis[j]&&low[j]>cost[p][j]){
low[j]=cost[p][j];
pre[j]=p;
}
}
}
return ans;
}
贴上一个例题
https://vjudge.net/problem/OpenJ_Bailian-1679
代码明天发