描述:无。
原理:最小生成树的相关定理。
代码:
#include<bits\stdc++.h>
using namespace std;
typedef int CostType;
class Edge{
public:
int u;
int v;
CostType cost;
Edge(){}
Edge(int x,int y,CostType c):u(x),v(y),cost(c){}
Edge operator =(Edge a){
this->u=a.u;
this->v=a.v;
this->cost=a.cost;
return *this;
}
};
int cmp_Edge(Edge a,Edge b){
if(a.cost>b.cost) return 1;
else if(a.cost==b.cost) return 0;
else return -1;
}
int kruskal(Edge* E,int vn,int em){
/* 求一个图的最小生成树。
E表边集。
vn为顶点数,顶点编号为0,1,2,……n-1。
em为边数。
*/
sort(E,E+em,cmp_Edge);
int concent[vn]; //判断点属于哪一连通分支,等于-1表示该点还未选择。
int pre[vn]; //在这之前加入同一连通分支的前一个点。
int now_con[vn]; //加入第i个连通分支的最近的点。
memset(concent,-1,vn);
memset(pre,-1,vn);
memset(now_con,-1,vn);
int con=0;
int min_cost=0;
for(int i=0;i<em;i++){
min_cost+=E[i].cost;
if(concent[E[i].v]==-1){
if(concent[E[i].u==-1]){
concent[E[i].u]=concent[E[i].v]=con;
pre[E[i].u]=pre[E[i].v]=E[i].v;
now_con[con]=E[i].u;
}
else{
concent[E[i].v]=concent[E[i].u];
pre[E[i].v]=now_con[concent[E[i].v]];
now_con[concent[E[i].v]]=E[i].v;
}
}
else {
if(concent[E[i].u]==-1){
concent[E[i].u]=concent[E[i].v];
pre[E[i].u]=now_con[concent[E[i].u]];
now_con[concent[E[i].u]]=E[i].u;
}
else if(concent[E[i].u]!=concent[E[i].v]){
int l0=concent[E[i].v];
int l1=concent[E[i].u];
int k=now_con[l1];
int k0=k;
while(pre[k]!=k){
concent[k]=l0;
k=pre[k];
}
concent[k]=l0;
pre[k]=now_con[l0];
now_con[l0]=k0;
}
else{min_cost-=E[i].cost;}
}
}
if(concent[0]==-1) return -1;
for(int i=1;i<vn;i++)
if(concent[i]!=concent[i-1]) return -1;
return min_cost;
}
后记:中间过程太琐碎。代码为调试。