[ABC235] E - MST + 1

[Q] https://atcoder.jp/contests/abc235/tasks/abc235_e

・「最小全域木」とあるのでクラスカル法をエスパー。
Q. クラスカル法?
A. コストが低い辺から順にUniteする、ただのUnionFind。

・与えられたMで最初に木を作ってしまったら、Qの比較をどうしよう?
1. QとMが同じ辺ならcost比較できるけど、
2. 新たな辺Qを採用する場合、木の周辺構造が影響しそう。「組み換え」考慮するのきつそう。
[tips] 辺Qについている頂点ABから生えている辺を全部みる、などする「HL分解」ACルートがある。

でも、今回はクラスカルで実装。
1. 木を作ってしまうと、Q判定が難しくなってしまう。
2. クエリも含めて、M+Qまるっと全部クラスカル法してしまえばよさそう。
3. Mの辺が来たらUniteするし、Qの辺が来たらYesにすればいい。

Q. コストでソートしたいけど、4要素をもつ配列?
A. tuple<int, int, int, int> // cost, A, B, id
tupleの超簡単な使い方

 ll N;
 cin >> N;

 // 値の代入
 vector<tuple<ll, ll, ll, ll>> T(N);
 rep(i, N){
   ll x, y, z;
   cin >> x >> y >> z;
   T[i] = {x, y, z, i};
 }
 
 // 値の取り出し
 rep(i, N){
   auto&[a, b, c, d] = T[i];
   cout << a << " " << b << " " << c << " " << d << endl;
 }

実装

ll N, M, Q;
bool ans[200020];

int main(){
 cincout();
 
 cin >> N >> M >> Q;
 G.assign(N+1, vector<ll>());
 seen.assign(N+1, false);  
 UnionFind tree(N);
 
 // tuple<ll, ll, ll, ll> を入れる
 vector<tll> T;
 rep(i, M){
   ll a, b, c;
   cin >> a >> b >> c;
   --a, --b;
   T.push_back({c, a, b, -1}); // cost, a, b, id どうせ結合するからidいらない
 }
 
 rep(i, Q){
   ll u, v, w;
   cin >> u >> v >> w;
   --u, --v;
   T.push_back({w, u, v, i}); // cost, u, v, id
 }

 // solve
 sort(all(T));
 rep(i, M+Q){
   auto&[c, a, b, d] = T[i];
   // もう同じ集合に属するなら採用しない
   if (tree.issame(a, b)) continue;
   // Q
   if (d != -1){
     ans[d] = true;
   }
   // M
   else{
     tree.unite(a, b);
   }
 }
 rep(i, Q){
   if (ans[i]) cout << "Yes" << endl;
   else cout << "No" << endl;
 }
}

https://atcoder.jp/contests/abc235/submissions/28548433


この記事が気に入ったらサポートをしてみませんか?