【Kruskal算法】(最小生成树)
【Kruskal算法】
模版题 https://www.acwing.com/file_system/file/content/whole/index/content/4386/
思路
(1)将所有边按权重从小到大排序
(2)枚举每条边a-b 权重为c
if(a,b不连通) //并查集思想
将这条边加入集合中
模版代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
//不需要邻接表/邻接矩阵->结构体存边即可
//注意这里虽然是无向图 但是因为存每一条连边 所以不需要存两次
int n,m;
int p[N];//并查集
struct Edge{
int a,b,w;
bool operator< (const Edge &W)const{
return w<W.w;
}
}edges[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m;
for(int i=0;i<m;i++){
int a,b,w;
cin>>a>>b>>w;
edges[i]={a,b,w};
}
sort(edges,edges+m);
//初始化并查集
for(int i=1;i<=n;i++) p[i]=i;
//从小到大枚举所有边
int res=0,cnt=0;
for(int i=0;i<m;i++){
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=find(a);
b=find(b);
if(a!=b){
p[a]=b;//两集合合并
res+=w;//求权重和
cnt++;//当前加了多少条边
}
}
if(cnt<n-1) cout<<"impossible";//该图不连通
else cout<<res;
return 0;
}
最大生成树
以下两种方法挑一种即可
(1)优先队列把从小到大改成从大到小
(2)把边权改成相反数
题目积累
黑白树
https://acm.hdu.edu.cn/contest/problem?cid=1202&pid=1008
题目大意

思路
一棵树的节点树为n,那么他的边数一定为n-1
将白边边权设为1,黑边边权设为0,
注意这里是生成树:需要包含所有节点,边数固定为n-1
那么求最小生成树时,可以得到白边的下限,反之求最大生成树可以求得白边上限
由于边数固定,白边固定可自动推黑边个数:那么答案就是白边上下限
代码
int n,m;
struct DSU {
vector<int> fa;
DSU(int n) : fa(n + 1) {
iota(fa.begin(), fa.end(), 0);
}
int get(int x) {
while (x != fa[x]) {
x = fa[x] = fa[fa[x]];
}
return x;
}
bool merge(int x, int y) { // 设x是y的祖先
x = get(x), y = get(y);
if (x == y) return false;
fa[y] = x;
return true;
}
bool same(int x, int y) {
return get(x) == get(y);
}
};
struct Tree {
using TII = tuple<int, int, int>;
int n;
priority_queue<TII, vector<TII>, greater<TII>> ver;
Tree(int n) {
this->n = n;
}
void add(int x, int y, int w) {
ver.emplace(w, x, y); // 注意顺序
}
int kruskal() {
DSU dsu(n);
int ans = 0, cnt = 0;
while (ver.size()) {
auto [w, x, y] = ver.top();
ver.pop();
if (dsu.same(x, y)) continue;
dsu.merge(x, y);
ans += w;
cnt++;
}
if(cnt < n - 1) return -1; // 输入有误,建树失败
return ans;
}
};
struct Tree2 {
using TII = tuple<int, int, int>;
int n;
priority_queue<TII, vector<TII>, less<TII>> ver;
Tree2(int n) {
this->n = n;
}
void add(int x, int y, int w) {
ver.emplace(w, x, y); // 注意顺序
}
int kruskal() {
DSU dsu(n);
int ans = 0, cnt = 0;
while (ver.size()) {
auto [w, x, y] = ver.top();
ver.pop();
if (dsu.same(x, y)) continue;
dsu.merge(x, y);
ans += w;
cnt++;
}
if(cnt < n - 1) return -1; // 输入有误,建树失败
return ans;
}
};
void solve(){
cin>>n>>m;
Tree tree(n);
Tree2 tree2(n);
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
tree.add(u,v,w);
tree2.add(u,v,w);
}
int ans=tree2.kruskal();
if(ans==-1){
cout<<0<<endl;
return;
}
ans=ans-tree.kruskal()+1;
cout<<ans<<endl;
}

浙公网安备 33010602011771号