最小生成树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