0
点赞
收藏
分享

微信扫一扫

7-50 畅通工程之局部最小花费问题(最小生成树)

转角一扇门 2022-03-25 阅读 45
  • 题目链接:7-50 畅通工程之局部最小花费问题
  • 考查知识:最小生成树
  • 题意描述:
    • 给出村庄数目N (1≤N≤100),道路N(N−1)/2条。
    • 两村庄间有道路的成本,以及修建状态:1表示已建,0表示未建。
    • 计算出全地区畅通需要的最低成本
  • 思路简析:
    • 最小生成树模板题了
  • 具体代码
    • prim算法
      板子一

      	#include<bits/stdc++.h>
      	using namespace std;
      	typedef long long ll;
      	const int N=2e2,inf=0x3fffffff;
      	int e[N][N],d[N],vis[N];
      	int prim(int n,int s){//总共n个顶点,起点为s 
      		fill(d,d+N,inf);d[s]=0;//初始化数组d 
      		int ans=0;//最小生成树边权之和
      		for(int i=0;i<n;i++){//n次将点加入最小生成树 
      			int u=-1,mi=inf;
      			for(int j=1;j<=n;j++){//编号[1,n] 
      				if(!vis[j]&&d[j]<mi){
      					u=j;
      					mi=d[j];
      				}
      			}
      			if(u==-1)break;//不连通,无法构建最小生成树
      			vis[u]=1;ans+=d[u]; 
      			for(int j=1;j<=n;j++){//编号[1,n]
      				if(!vis[j]&&e[u][j]<d[j])d[j]=e[u][j];
      			}
      		} 
      		return ans; 
      	} 
      	int main(){
      		int n,m,x,y,z,w;
      		cin>>n;
      		m=n*(n-1)/2;
      		fill(e[0],e[0]+N*N,inf);
      		for(int i=1;i<=n;i++)e[i][i]=0;	
      		for(int i=1;i<=m;i++){//编号[1,n]
      			cin>>x>>y>>z>>w;
      			if(!w)e[x][y]=e[y][x]=z;
      			else e[x][y]=e[y][x]=0;
      		}
      		cout<<prim(n,1);
      		return 0;
      	}
      
      

      板子二,优先推荐

      #include<bits/stdc++.h>
      using namespace std;
      typedef long long ll;
      const int N=1e2+10,inf=0x3fffffff;
      int e[N][N],d[N],n,m,ans;
      bool v[N];
      void prim(int s){
      	fill(d,d+N,inf);
      	memset(v,0,sizeof(v));
      	d[s]=0;
      	for(int i=1;i<n;i++){
      		int x=0;
      		for(int j=1;j<=n;j++)
      			if(!v[j]&&(x==0||d[j]<d[x]))x=j;
      		v[x]=1;
      		for(int y=1;y<=n;y++)
      			if(!v[y])d[y]=min(d[y],e[x][y]);
      	} 
      } 
      int main(){
      	cin>>n;
      	m=n*(n-1)/2;
      	//构建邻接矩阵 
      	fill(e[0],e[0]+N*N,inf);
      	for(int i=1;i<=n;i++)e[i][i]=0;
      	for(int i=1;i<=m;i++){
      		int x,y,z,w;
      		cin>>x>>y>>z>>w;
      		if(!w)e[x][y]=e[y][x]=min(e[x][y],z);
      		else e[x][y]=e[y][x]=0;
      	}
      	//求最小生成树
      	int s=1;
      	prim(s);
      	for(int i=1;i<=n;i++)ans+=d[i];
      	cout<<ans<<endl; 
      	return 0;
      }
      
      
    • kruskal算法

举报

相关推荐

0 条评论