洛咕博客地址: − > C l i c k H e r e < − ->Click Here<- −>ClickHere<−,求捧场
万金油 K r u s k a l Kruskal Kruskal
据说 P r i m Prim Prim适用于稠密图?然而好久没写了…… e m m emm emm
算了江一下 K r u s k a l Kruskal Kruskal好了……因为 K r u s k a l Kruskal Kruskal实在是太好理解了……
回顾最小生成树的定义……在一个图中选取若干条边使图连通且边权的和最小
不会的人第一想法肯定是贪心吧……先排个序再瞎搞
K r u s k a l Kruskal Kruskal也就是这样的……不过比纯种贪心多了一些东西……就是并查集,可以用来查询是否连通
这一点很好理解吧,如果两个块已经连通了就不用再选边了
根据上述内容,我们可以写出一个 K r u s k a l Kruskal Kruskal的流程……
1、对所有边按权值从小到大排序
2、遍历每条边
3、判断边两端的块是否连通
4、如果不连通,使答案加上权值,并将两块合并
5、如果连通,跳过
6、重复2~5,直到取的边数到达目标
代码如下
struct Edge
{
int u,v,dis;
friend bool operator < (const Edge &x,const Edge &y)
{
return x.dis<y.dis;
}
}t[100005];
int Find(int x)
{
return x==f[x]?x:f[x]=Find(f[x]);
}
void Merge(int x,int y)
{
x=Find(x);
y=Find(y);
if(x^y) f[x]=y;
}
void Kruskal()
{
sort(t+1,t+m+1);
for(int i=1;i<=m;i++)
{
int p=Find(t[i].u),q=Find(t[i].v);
if(p!=q)
{
ans+=t[i].dis;
Merge(p,q);
num++;
if(num==n-1) break;
}
}
}