最小生成树(Prim):
算法描述
MST(Minimum Spanning Tree,最小生成树)问题有两种通用的解法,Prim算法就是其中之一,它是从点的方面考虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点v0,将该点加入集合V,再从集合U-V中找到另一点v1使得点v1到V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={v0,v1},再从集合U-V中找到另一点v2使得点v2到V中任意一点的权值最小,此时将v2点加入集合V,直至所有顶点全部被加入V,此时就构建出了一颗MST。因为有N个顶点,所以该MST就有N-1条边,每一次向集合V中加入一个点,就意味着找到一条MST的边。
Prim算法适用于稠密图 ,Kruskal适用于稀疏图
例题:
题目描述
经过特色示范羊村检查,检查组觉得羊村的道路需要重修,破败的道路,会影响到小羊们上学的安全。
村长组织施工队,开始丈量距离,规划施工方案,已经得到了若干建筑物间修建道路的可行方案,共有N个建筑物,和M条可选道路。这些路保证可以将N个建筑相连。
最终方案中,羊村打算修建全球最豪华的全大理石道路,道路可以双向通行,且一体成型,路中无缝隙。为了达到这个设计要求,就必须自建大理石工厂!
大理石工厂建造的难度在于,必须根据其需要生产最大长度的大理石来设计。工厂可以生产出不超过其设计极限的任意长度的大理石。例如,设计长度为100的工厂,可以生产100、90等长度的大理石,但是不能生产长度为101的大理石。
羊村的预算有限,希望你能帮忙规划出一个修路方案,使得工厂的设计规模尽可能小,且可以保证其能生产的大理石可以连通所有羊村的建筑。求出工厂的最小设计规模。
输入
第一行两个整数N和M,N表示羊村中的建筑数量,M表示可以修建的道路数量。
接下来M行,每行三个整数Ai,Bi和Ci,表示从建筑Ai,到建筑Bi,可以修建一条长度为Ci的道路。
注意,建筑编号从1到N,两个建筑之间可能有多条道路。
输出
输出大理石工厂的最小设计规模。
样例输入
3 3
1 2 100
2 3 101
1 3 99
样例输出
100
数据范围限制
30%的数据N<=10,N-1<=M<=100。
100%的数据1<=N<=2000,N-1<=M<=10000,1<=Ai,Bi<=N,1<=Ci<=1000000000。
提示
只要修建1到2,以及1到3的道路,就可以使得3个建筑相互连通,且最大值只有100,只需要建造设计规模为100的大理石工厂,就可以生产出长度为100和99的大理石。
这道题其实就是一道模板题,只不过是将求边权和改为了最大边权。
#include<cstdio>
#include<iostream>
#include<cstring>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int INF=2147483647;
int n,m,u,v,w,c[2010][2010],lowcost[2010],ans;
bool vis[2010];
void input()
{
memset(c,0x7f,sizeof(c));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
c[u][v]=c[v][u]=min(c[u][v],w);
}
}
void Prim()
{
int v=1;
vis[v]=1;
for(int i=1;i<=n;i++) lowcost[i]=c[v][i];
for(int i=1;i<n;i++) //还需要生成n-1的点
{
int temp=INF,t;
for(int j=1;j<=n;j++)
if(lowcost[j]<temp&&!vis[j])
temp=lowcost[j],t=j;
vis[t]=1;
v=t;
ans=max(ans,temp);
for(int j=1;j<=n;j++)
if(lowcost[j]>c[v][j]&&!vis[j])
lowcost[j]=c[v][j];
}
}
int main()
{
//fre(road);
input();
Prim();
printf("%d",ans);
return 0;
}