最小生成树
NO.1 kruscal
这是一个样例:
首先 我们要把所有边的长度按长度从小到大排列,如下
1 2 2
1 3 2
1 4 3
3 4 3
2 3 4
从前往后枚举. 每一次 如果一条边的两个点不在一个合集里面 就将两点加入 就得到了如下:
示例代码
bool cmp(node a,node b) {
return a.w<b.w;
}
int find(int x){//并查集
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
bool kruscal(){
int cut=0;
for(int i=1;i<=n;i++) fa[i]=i;
sort(l+1,l+m+1,cmp);
for(int i=1;i<=m;i++){
int A=find(l[i].x),B=find(l[i].y);
if(A!=B){//不在一个集合里
fa[A]=B;
ans+=l[i].w;
cut++;
}
if(cut==n-1) return 1;//最小树算完
}
return 0;
}
NO.2 prim
一样的样例:
按照点来枚举,每一次寻找那个点距离已经确认好的最小生成树最近的一条边 ,并连接。 最终也能得到相同的结果:
示例代码
void add(int x,int y,int z){
ver[++tot]=y,edg[tot]=z;
nxt[tot]=head[x],head[x]=tot;
}
bool prim(){
priority_queue< PII,vector<PII>,greater<PII> > Q;
memset(dis,0x3f,sizeof(dis));
dis[1]=0;Q.push({0,1});
while(!Q.empty()){
int x=Q.top().second,ds=Q.top().first;Q.pop();
if(vis[x]) continue;vis[x]=1;
ans+=ds,cnt++;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i],w=edg[i];
if(dis[y]>w){
dis[y]=w;
Q.push({w,y});
}
}
}
return cnt==n;
}