最小生成树
kruskal算法求最小生成树,把所有的边进行排序,然后依次加入n-1条边,中间要判断是否有环路
用到并查集f,初始化的时候每个点的f都是自己,只要遍历到一条边,就判断两个点是否有共同的f,也就是两个点是否是连通的。
不是就加入到最小生成树中,并且把这两个其中一个的父亲结点更新为另一个点的父亲结点。
//***最小生成树算法***
//Kruskal算法
//图必须是无向图
#include<bits/stdc++.h>
using namespace std;
const int N=1000;
int n,m,qi,zh,ans,cnt;
int f[N];
struct node
{
int x,y,d;
}G[N];
bool cmp(node a,node b)
{
return a.d<b.d;
}
int findf(int i)
{
return i=f[i]?i:findf(f[i]);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>G[i].x>>G[i].y>>G[i].d;
}
sort(G+1,G+m+1,cmp);
//每一个点都是一个独立的连通分量
for(int i=1;i<=n;i++)
{
f[i]=i;
}
//只需要n-1条边,此时所有的边已经排序好
for(int i=1;i<=m;i++)
{
//考察方法就是考察边的两个结点
int f1=findf(G[i].x);
int f2=findf(G[i].y);
if(f1!=f2)
{
ans+=G[i].d;
f[f1]=f2;
cnt++;
if(cnt==n-1)
break;
}
}
cout<<ans<<endl;
}
/*
5 7
1 2 4
1 4 2
2 4 1
2 3 4
4 3 1
4 5 7
3 5 3
*/
Prim算法求最小生成树算法
维护一个dis数组,初始化为无穷,初始化先把1加进去,然后进行n-1次循环把其他最小的结点依次加进去,如果在循环中间出现了找不到一个最小点,也就是都是INF,说明无法生成最小生成树,根本就不连通。
//***最小生成树算法***
//prim算法
//图必须是无向图
#include<bits/stdc++.h>
using namespace std;
const int N=1000;
const int INF=0x3f3f3f3f;
int n,m,qi,zh,ans,cnt,quan;
int G[N][N];
int dis[N];//图到某个点的距离
bool book[N];//是否加入到图中
//每次都用新加入的边去更新所有点到s的距离
int prim()
{
//初始化先把1加进去
dis[1]=0;
book[1]=1;
for(int i=1;i<=n;i++)
{
dis[i]=min(dis[i],G[1][i]);
}
//之后加n-1个距离s最小的结点
//而且每次加都更新所有邻接结点
for(int i=2;i<=n;i++)
{
int u;
int minn=INF;
int t=-1;
for(int i=1;i<=n;i++)
{
if(dis[i]<minn&&!book[i])
{
t=1;
u=i;
minn=dis[i];
}
}
if(t==-1)//在循环里面就没有找到合适的结点加入
return -1;
book[u]=1;
ans+=dis[u];
for(int i=1;i<=n;i++)
{
dis[i]=min(dis[i],G[u][i]);
}
}
return ans;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
G[i][j]=INF;
}
dis[i]=INF;
}
for(int i=1;i<=m;i++)
{
cin>>qi>>zh>>quan;
G[qi][zh]=quan;
G[zh][qi]=quan;
}
cout<<prim();
}
/*
5 7
1 2 4
1 4 2
2 4 1
2 3 4
4 3 1
4 5 7
3 5 3
*/