题解 luogu P3366 【【模板】最小生成树】

最小生成树kruskal算法!

最弱红名的首道图论题

贪心算法,按边的权值排序,然后看当前指定的两点有木有已经在一棵树上,如果有,不管,没有,merge。然后ans加上那条边的权值。

#include<bits/stdc++.h>
using namespace std;
struct path
{
	int k,l,q;
}p[200000];
int bcj[200000];
int get(int x)
{
	if (bcj[x]==x)return x;
	else return bcj[x]=get(bcj[x]);
}
void merge(int x,int y)
{
	bcj[get(x)]=get(y);
}//标准的并查集get和merge
void haha(int l,int r)
{
    int i,j,x,y,n;
    x=p[(l+r)/2].q;i=l;j=r;
    do{
    while(p[i].q<x)i++;
    while(p[j].q>x)j--;
    if (i<=j)
    {swap(p[i].q,p[j].q);swap(p[i].k,p[j].k);swap(p[i].l,p[j].l);i++;j--;}
    }while(i<=j);
    if (i<r)haha(i,r);
    if (j>l)haha(l,j);
}//快排
int main()
{
	int i,j,x,y,n,ans=0;
	cin>>x>>y;
    for (i=1;i<=x;i++)bcj[i]=i;//初始化并查集
	for (i=1;i<=y;i++)
	{
		int k,l;
		cin>>p[i].k>>p[i].l>>p[i].q;
	}//读入边
	haha(1,y);
	for (i=1;i<=y;i++)
		if (get(p[i].k)!=get(p[i].l)){merge(p[i].k,p[i].l);ans+=p[i].q;};//如果不在同树上就合并
	for (i=1;i<=x;i++)
	{
		if (get(i)!=get(1)){cout<<"orz";return 0;}
	}//如果有多个树根,输出orz
	cout<<ans;
	return 0;
}

the end

猜你喜欢

转载自blog.csdn.net/qq_39441542/article/details/84675092