クラスカル法
最小全域木を求める.AOJ
依存
計算量
$O(|E|\log|E|)$(本当?)
ソースコード
struct UnionFind{
public:
vector<int> par;//親
vector<long> weight;//重み
vector<long> weightAlone;//単体の重み
UnionFind(int n):par(n),weight(n),weightAlone(n){
for(int i=0;i<n;i++){
par[i]=i; //親は自分自身にしておく
weight[i] = weightAlone[i] = 1;
}
}
//途中で実行すると壊れます
void setWeight(int i,long w){
weight[i] = weightAlone[i] = w;
}
//途中で実行しても大丈夫
void changeWeight(int i,long w){
long pre = weightAlone[i];
weightAlone[i] = w;
weight[root(i)] += w-pre;
}
int root(int x){
if(par[x]==x){
return x;
}else{
int r = root(par[x]);
par[x]=r;
return r;
}
}
void unite(int x,int y){
int rx=root(x);
int ry=root(y);
if(rx==ry){
return;
}
par[rx]=ry;
weight[ry] += weight[rx];
}
bool same(int x,int y){
int rx=root(x);
int ry=root(y);
return rx==ry;
}
long getWeight(int x){
return weight[root(x)];
}
vector<vector<int>> getGroups(){
vector<vector<int>> res;
map<int,vector<int>> mp;
for(int i=0;i<(int)par.size();i++){
mp[root(i)].push_back(i);
}
for(auto&[k,v]:mp){
(void)k; //使いません
res.push_back(v);
}
return res;
}
};
/*クラスカル法*/
struct Edge{
int from;
int to;
long cost;
};
using Graph = vector<vector<Edge>>;
struct Kruskal{
vector<Edge> edges;
Graph G;
int V;
Kruskal(int V):V(V){
G.resize(V);
}
//無向グラフ!
void addEdge(int from,int to,long cost){
edges.push_back({from,to,cost});
}
long long build(){
sort(edges.begin(),edges.end(),[](const Edge& e1,const Edge& e2){
return e1.cost<e2.cost;
});
UnionFind uf(V);
long long res = 0;
for(auto& e:edges){
if(!uf.same(e.from,e.to)){
uf.unite(e.from,e.to);
res += e.cost;
G[e.from].push_back({e.from,e.to,e.cost});
G[e.to].push_back({e.to,e.from,e.cost});
}
}
return res;
}
};