7-10 公路村村通

/*
https://pintia.cn/problem-sets/15/problems/718
数据结构与算法题目集(中文)7-10
*/
/*通过的代码以及注释,注释最多的地方,是思考的最多的地方*/
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1005
/*下次不要用N来命名,不然容易和下面的n弄混,unnecessarily*/
int f[N];
/*树的母节点,例如节点1的母节点f[1]=2,那么2就是节点1的母节点*/
struct edge
{
	int l,r,dis;
	bool friend operator < (edge a,edge b)
/*操作符重载,记得这种sort排序结构体数组的格式,因为没有深入学习*/
	{
		return a.dis<b.dis;
	}
}e[N<<2];
int sanda(int a)
/*sanda=search and adjust——搜索母节点并且调整母节点*/
/*这个函数就是用来告诉你母节点是谁,在那之前,母节点会被调整为最顶层的母节点——节点a的母节点是自己,
即a=f[a]——这个最终的母节点的值相当于不同森林的编号*/
{
	if(a==f[a]) return f[a];
/*找到了最终的母节点*/
	else
	{
		f[a]=sanda(f[a]);
/*我的母节点的母节点的母节点的母节点……是我的母节点,在找到原始点后,
最终效果相当于直接把原始点当做自己的直接母节点,当然在那之前,它原来的母节点已经先行完成这一操作了*/
/*不用担心操作在中间进行而导致不能一次性更新完全,反正下一次用到它,
它还是要先完成找到最终的母节点才能进行操作的,而只要它之前有母节点,就能顺藤摸瓜*/
		return f[a];
	}
}
int main()
{
	int n,m,cnt=0,sum=0;
	
	cin>>n>>m;
	int i,j,k;
	for(i=1;i<=m;i++)
	{
		cin>>e[i].l>>e[i].r>>e[i].dis;
	}
	for(i=1;i<=n;i++)
	f[i]=i;//Kluskar算法——勿在浮沙筑高台http://blog.csdn.net/luoshixian099/article/details/51908175
	sort(e,e+m);
	for(i=1;i<=m;i++)
	{
		if(cnt==n-1) break;
		int fa=sanda(e[i].l);
		int fb=sanda(e[i].r);
		if(fa==fb) continue;
		//如果节点fa和fb在同一棵森林里面,就继续
		sum+=e[i].dis;
		f[fa]=f[fb];
		cnt++;
	}
	if(cnt==n-1) cout<<sum;
	else cout<<-1;
	return 0;	
} 





/*这个是看了最小生成树的原理,但是还没有掌握两种算法时写的*/
/*评测:过三卡二,运行超时*/
#include<cstdio>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
using namespace std;
#define inf 0x3fffffff
#define MAX 1001
int p[1001][1001];
bool vis[1001];
int sum=0;
int n,m;
void dfs(int v0)
{
	vis[v0]=1;
	int i,j,k;
	for(k=0;k<n-1;k++)
	{
		int mi=inf,wp=0;
		for(i=1;i<=n;i++)
		{
			if(!vis[i])
			{
				for(j=1;j<=n;j++)
				{
					if(vis[j])
					{
						if(p[i][j]<mi)
						{
							mi=p[i][j];
							wp=i;
						}
					}
				}
			}
		}
		vis[wp]=1;
		sum+=mi;
		
	}
}
int main()
{
	int i,j,k;
	for(i=0;i<1001;i++) vis[i]=0;
	for(i=0;i<MAX;i++)
	for(j=0;j<MAX;j++)
	{
		p[i][j]=inf;
		p[j][i]=inf;
	}
	
	for(i=0;i<MAX;i++)
	p[i][i]=inf;
	cin>>n>>m;
	for(i=0;i<m;i++)
	{
		int x,y,l;
		cin>>x>>y>>l;
		p[x][y]=l;
		p[y][x]=l;
	}
	dfs(1);
	int flag=1;
	for(i=1;i<=n;i++)
	{
		if(!vis[i])
		{
			flag=0;	
			break;
		}
	 } 
	if(flag)
	cout<<sum; 
	else
	cout<<-1;
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值