最小生成树算法(krustra+prime)
给你一个图,求让图连通的边权和最小值
krustra算法是基于加边法,将所有边权排序,每次加一条边,将两个点放在同一个集合中。如果新加的点不在同一个集合中,就合并(并查集)
涉及到排序,可以用结构体存节点的信息,之后按边权从小到大排序。随后遍历n条边,判断两个节点是否在一个集合中,不在则加入
int find(int x) { if(x==father[x]) return x; else return find(father[x]); } bool Union_set(int x,int y) { int lx=find(x),ly=find(y); if(father[lx]==father[ly]) return 0; else { father[lx]=ly; return 1; } int krustra() { for(int i=1;i<=n;i++) father[i]=i; } sort(edge,edge+n,cmp); for(int i=1;i<=num;i++)//num为边的总数 { int x=edge[i].lx,y=edge[i].ly; if(union_set(x,y)) ans+=edge[i].value; } return ans; }
这个问题还可以引申一下,如果只需要将若干个点连通。那么我们在每次做完之后,进行一下判断,判断我们所求的点是否在一个集合中了。(当然可以想象这个时间复杂度会很高)
Prime算法(加点法,从一个点出发找离他最近的点,然后依次中间点进行更新)
for(int i=2;i<=n;i++) dfs[i]=inf; dfs[1]=0; while(1) { int min=inf,pos; for(int i=1;i<=n;i++) { if(!visit[i]&&min>dfs[i]) min=dfs[i];pos=i; } if(min==inf) break; visit[pos]=1; ans+=min;//边权值累加 for(int j=1;j<=n;j++) { if(dfs[j]>edge[pos][j]) dfs[j]=edge[pos][j]; } } return ans;