ホームに戻る
最小全域木
// クラスカル法
// コストの小さい枝から評価していく、
// このとき枝を繋いでループにならなければ繋ぐ。
// 全ての枝についてこれを行えば最小全域木になる。
// ループになるかどうかの検出はUnion-Findを用いる。
// O(E+VlogV)
vector<int> uf, usz;
int nc;
void init(int n){
vector<int> uf_(n);
vector<int> usz_(n, 1);
uf = uf_;
usz = usz_;
nc = n;
for(int i = 0; i < uf.size(); i++){
uf[i] = i;
}
}
int find(int a){
return (uf[a] == a) ? a : uf[a] = find(uf[a]);
}
void union_(int a, int b){
a = find(a);
b = find(b);
if(a != b){
if(usz[a] >= usz[b]){
swap(a, b);
}
uf[a] = b;
usz[b] += usz[a];
nc--;
}
}
int check(int a, int b){
return (find(a) == find(b)) ? 1 : 0;
}
int get_size(int a){
return usz[find(a)];
}
// vector<pair<コスト,pair<元,先> > > であること
long long minST(vector<pair<long long,pair<long long, long long> > > &v, long long V){
init(V);
long long ret = 0;
sort(v.begin(),v.end());
for(long long i = 0; i < v.sz; i++){
long long from = v[i].se.fi;
long long to = v[i].se.se;
long long cost = v[i].fi;
if(check(from,to)==0){
union_(from,to);
ret += cost;
}
}
return ret;
}