2020寒假【gmoj2183】【road羊羊吃草】【最小生成树:普里姆&克鲁斯卡尔+并查集】

题目描述

经过特色示范羊村检查,检查组觉得羊村的道路需要重修,破败的道路,会影响到小羊们上学的安全。
村长组织施工队,开始丈量距离,规划施工方案,已经得到了若干建筑物间修建道路的可行方案,共有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的大理石。

分析

一开始我还理解为了删边求连通性的问题。
其实是最小生成树,可以用prim或者kruskal+并查集两种方法,我两种都做了。
有点变式:把累加路径和变成求边权最大值

上代码

prim
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,a[2001][2001],dis[2001],f[2001],ans;
void prim()
{
	memset(dis,0x7f,sizeof(dis));
	dis[1]=0;
	for(int i=1;i<=n;i++)
	{
		int v=a[0][0],k=0;
		for(int j=1;j<=n;j++)
		{
			if(dis[j]<v&&!f[j])
			{
				v=dis[j];
				k=j;
			}
		}
		if(k==0) return;
		f[k]=1;
		ans=max(ans,v);
		for(int j=1;j<=n;j++)
		{
			if(a[k][j]<dis[j]&&!f[j])
			{
				dis[j]=a[k][j];
			}
		}
	}
}
int main()
{
	freopen("road.in","r",stdin);
	freopen("road.out","w",stdout);
	cin>>n>>m;
	memset(a,0x7f,sizeof(a));
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		a[x][y]=a[y][x]=min(a[x][y],z);
	}
	prim();
	cout<<ans;
	fclose(stdin);
	fclose(stdout);
	return 0;
 } 
kruskal
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,k,fa[2010],xx,yy,ans;
struct node
{
    int x,y,z;
}a[10010];
int cmp(node l,node r)
{
    return l.z<r.z;
}
int father(int h)
{
    while(h!=fa[h])
    {
    	h=fa[h];
	}
    return h;
}
int main()
{
    freopen("road.in","r",stdin);
    freopen("road.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>a[i].x>>a[i].y>>a[i].z;
	}
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=n;i++)
    {
    	fa[i]=i;
	} 
	for(int i=1;i<=m;i++)
	{
        xx=father(a[i].x);//并查集 
        yy=father(a[i].y);
        if(xx!=yy)
        {
            ans=max(ans,a[i].z);
            fa[xx]=yy;
        }
    }
	cout<<ans;
	fclose(stdin);
	fclose(stdout);
	return 0; 
}

————————————剧终———————————

发布了110 篇原创文章 · 获赞 100 · 访问量 8006

猜你喜欢

转载自blog.csdn.net/dglyr/article/details/105185494