提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一.Kruskal算法
1.算法思想
这是最小生成树的算法之一,它的本质思想就是把所有的边,用其边权的大小,从小到大的顺序排列,从小到大依次遍历,如果没有添加这两点之间的边权并且在添加这条边的基础上没有形成环,那么就添加这条边,依次进行,当有n-条边的时候就结束.
主要思想就是贪心
2.时间复杂度
O(ElogE)
3.算法模板
void kruskal()
{
int ans = 0;
int cnt = 0;
for(int i= 0;i<e.size();i++)
{
int u = e[i].u;
int v = e[i].v;
int w = e[i].w;
u = find(u);
v = find(v);
if(u!= v)
{
f[u]= v;
ans+=w;
cnt--;
}
}
if(cnt==1) cout<<ans<<endl;//最小生成树的边权和;
}
4.相关例题
https://acm.dingbacode.com/showproblem.php?pid=1863
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int f[N];
int n ,m;
struct ma{
int u,v,w;
bool operator < (const ma &a) const{
return this->w<a.w;
}
};
vector<ma> e;
void innit()
{
for(int i=0;i<=m;i++)
{
f[i]=i;
}
e.clear();
}
int find(int x)
{
while(x!= f[x])x=f[x];
return x;
}
void kruskal()
{
int ans = 0;
int cnt = m;
for(int i= 0;i<e.size();i++)
{
int u = e[i].u;
int v = e[i].v;
int w = e[i].w;
u = find(u);
v = find(v);
if(u!= v)
{
f[u]= v;
ans+=w;
cnt--;
}
}
if(cnt==1) cout<<ans<<endl;//最小生成树的边权和;
else cout<<"?"<<endl;
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
innit();
for(int i = 1;i<=n;i++)
{
int u ,v ,w;
cin>>u>>v>>w;
e.push_back({u,v,w});
}
sort(e.begin(),e.end());
kruskal();
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
int pp[N];
int n,m,s,t;
struct edge{
int u,v,w;
bool operator<(const edge & a) const {
return w<a.w;
}
};
vector<edge> f;
void intin(int x)
{
for(int i=1;i<=x;i++ )
{
pp[i]=i;
}
}
int find(int x)
{
while(x!=pp[x]) x=pp[x];
return x;
}
int kruskal()
{
int ans=0;
int cnt=n;
for(int i=0;i<f.size();i++)
{
int u=f[i].u;
int v=f[i].v;
int w=f[i].w;
u=find(u);
v=find(v);
if(u!=v)
{
pp[v]=u;
ans=max(ans,w);
if(find(s)==find(t)) break;
}
}
cout<<ans<<endl;
}
int main()
{
cin>>n>>m>>s>>t;
intin(n);
for(int i=0;i<m;i++)
{
int u,v,w;
cin>>u>>v>>w;
f.push_back({u,v,w});
}
sort(f.begin(),f.end());
kruskal();
return 0;
}