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