图论 —— 生成树 —— 增量最小生成树
【概述】
所谓最小增量生成树问题,即:给定包含 n 个点的空图,依次加入 m 条带权边,每次加入一条边,就输出当前图中最小生成树的权值,如果没有生成树,则输出无解
求解最小增量生成树的方法是:根据最小生成树的回路性质,在原有最小生成树的基础上,每次增加一条边就会构成一个回路,那么去掉这个回路上权值最大的边,得到的就是新的最小生成树。
简单来说,每一次加边之前先跑一遍 Kruskal 找最小生成树,若已经有最小生成树,则新加入的边肯定会让其形成环,这时候开始进行删边操作,删去那个多余的边即可。
【模版】
struct Node {
int u,v;
int val;
bool operator<(const Node& rhs)const {
return val<rhs.val;
}
} edge[N];
int n,m,cnt;
int father[N];
int Find(int x) {
if(father[x]==x)
return x;
return father[x]=Find(father[x]);
}
void Kruskal() {
sort(edge,edge+cnt);
int pos=-1;
int res=0,mst=0;
for(int i=0; i<cnt; i++) {
int u=edge[i].u,v=edge[i].v;
int x=Find(u),y=Find(v);
if(x!=y) {
father[x]=y;
res++;
mst+=edge[i].val;
} else {
pos=i;
continue;
}
}
if(pos!=-1)
edge[pos]=edge[--cnt];
if(res!=n-1)
printf("-1\n");
else
printf("%d\n",mst);
}
int main() {
scanf("%d%d",&n,&m);
cnt=0;
for(int i=0; i<m; i++) {//添m次边
scanf("%d%d%d",&edge[cnt].u,&edge[cnt].v,&edge[cnt].val);
cnt++;
for(int i=0; i<N; i++)
father[i]=i;
Kruskal();//每次添边跑一次Kruskal
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】