题目大意:畅通工程的第n题了,这里就不再解释了。
解题思路:很裸的一道MST,唯一需要注意的地方就是对已经修建的路径的处理,直接将其权值置为0就可以了,详见code。
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1879
Prim code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 100+10;
const int INF =0x3fffffff;
int n,a,b,c,d;
int map[MAXN][MAXN],vis[MAXN],dist[MAXN];
int Prim(){
int sum=0; //各种初始化
for(int i=1;i<=n;i++) dist[i]=(i==1?0:map[1][i]);
memset(vis,0,sizeof(vis));
vis[1]=1;
for(int i=1;i<n;i++){
int pos,minn=INF;
for(int j=1;j<=n;j++) if(!vis[j] && dist[j]<minn) minn=dist[pos=j]; //寻找最短路径
vis[pos]=1;
sum+=minn; //路径求和
for(int k=1;k<=n;k++) //更新路径数组
if(!vis[k] && dist[k]>map[pos][k])
dist[k]=map[pos][k];
}
return sum;
}
int main(){
while(scanf("%d",&n)!=EOF && n){
for(int i=0;i<n;i++) //初始化图
for(int j=0;j<n;j++)
map[i][j]=INF;
for(int i=1;i<=n*(n-1)/2;i++){ //接收值
scanf("%d%d%d%d",&a,&b,&c,&d);
if(d==0) map[a][b]=map[b][a]=c;
else map[a][b]=map[b][a]=0; //已经修建的置为0,这样最短路径一定包含该条
}
printf("%d\n",Prim());
}
return 0;
}
再来一个Kruskal的code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN =100+10;
int n,tmp,a,b,c,d;
int p[MAXN];
struct edge{
int u,v,w;
}e[MAXN*MAXN];
int cmp(const edge a,const edge b){return a.w<b.w;}
int find(int x){return x==p[x]?x:find(p[x]);}
int Kruskal(){
int ans=0;
for(int i=1;i<=n;i++) p[i]=i;
sort(e+1,e+1+tmp,cmp);
for(int i=1;i<=tmp;i++){
int x=find(e[i].u);
int y=find(e[i].v);
if(x!=y){
p[x]=y;
ans+=e[i].w;
}
}
return ans;
}
int main(){
while(scanf("%d",&n)!=EOF && n){
tmp=n*(n-1)/2;
for(int i=1;i<=tmp;i++){
scanf("%d%d%d%d",&a,&b,&c,&d);
if(d==0){e[i].u=a;e[i].v=b;e[i].w=c;} //唯一需要注意的地方是这里对已经修建的权值处理
else{e[i].u=a;e[i].v=b;e[i].w=0;} //当然置0就可以了
}
printf("%d\n",Kruskal());
}
return 0;
}

本文介绍了最小生成树(MST)问题的两种经典算法——Prim算法和Kruskal算法,并通过具体实例展示了如何使用这两种算法解决畅通工程项目中的MST问题。文章提供了完整的代码实现,并详细解释了对于已修建路径的特殊处理。
207

被折叠的 条评论
为什么被折叠?



