7.2寡人的难题

最小生成树直接用kruskal就好了

#include<bits/stdc++.h>
#define sf scanf
#define scf(x) scanf("%d",&x)
#define scff(x,y) scanf("%d%d",&x,&y)
#define scfff(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define vi vector<long long>
#define mp make_pair
#define pf prlong longf
#define prf(x) printf("%d\n",x)
#define mm(x,b) memset((x),(b),sizeof(x))
#define rep(i,a,n) for (long long i=a;i<n;i++)
#define per(i,a,n) for (long long i=a;i>=n;i--)
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const double eps=1e-6;
const double pi=acos(-1.0);
const long long inf=0x7fffffff;    
const long long N=1e5+7;

struct Edge { 
	long long u, v, w; //边的顶点、权值
} edge[N*5]; //边的数组
long long pre[N];  //pre[i]为顶点 i 所在集合对应的树中的根结点
long long n, m;  //顶点个数、边的个数
long long Find( long long x ) 
{ //查找并返回节点 x 所属集合的根结点
	return pre[x]==x?x:pre[x]=Find(pre[x]);
}
bool cmp( Edge a, Edge b ) //实现从小到大排序的比较函数
{ 
	return a.w < b.w;
}
long long Kruskal( ) 
{
	for(int i=1;i<N;i++)pre[i]=i;
	sort(edge,edge+m,cmp);
	long long ans = 0;  //生成树的权值
	long long num = 0;  //已选用的边的数目
	long long u, v;  //选用边的两个顶点
	for(int i=0;i<m&&num<n-1;i++)
	{
		long long t1=Find(edge[i].u),t2=Find(edge[i].v);
		if( t1!=t2 ) 
		{
			//prlong longf( "%d %d %d\n", u, v, edge[i].w );
			ans += edge[i].w;
			num++;
			pre[t1]=t2;
			//pre[Find(t1)]=Find(t2);
		}
	}
	return ans;
}
int main( ) 
{
	long long u, v, w; //边的起点和终点及权值
	scff(n,m); //读入顶点个数 n
	rep(i,0,m)
		scfff(edge[i].u,edge[i].v,edge[i].w); 
	long long ans=Kruskal();
	cout<<ans;
	return 0;
}
posted @ 2018-12-08 13:24  一无所知小白龙  阅读(240)  评论(0编辑  收藏  举报