0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【ABC285_D】 UnionFindで解いてみた 【C++】

Last updated at Posted at 2023-01-22

abc285のD問題をUnionFindを使って解いてみました。
言語はC++です。

Point

  1. a → b → c → aと一巡したらダメそう
    • グラフ理論でいうところのサイクル(閉路)があるかどうかを検出
  2. 頂点が文字で与えられている
    • unordered_mapを使って番号に変換
  3. UnionFind(dsu)で頂点をグループ化
    • 既に閉路がある場合にさらにつなげる -> No
  4. 解けました!

コード例

d.cpp
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
#define rep(i, a, b) for (int i = a; i < b; i++)

int main(){
    int n;
    cin >> n;
    //mapだと遅いので基本unordered_mapを使う
    unordered_map<string, int> mp;
    vector<string> s(n), t(n);
    //頂点が文字列 -> mapで頂点数を取得する
    rep(i,0,n){
        cin >> s[i] >> t[i];
        //文字の頂点番号を取得
        //文字が重複したら、最初に記録した頂点番号を採用
        if(!mp.count(s[i])) mp[s[i]]=mp.size();
        if(!mp.count(t[i])) mp[t[i]]=mp.size();
    }
    int m = mp.size(); //頂点数の取得
    //Disjoint Set Union = Union Find (素集合データ構造)
    //素集合...二つの集合が交わりを持たないor互いに素
    //∴共通の元を持たない
    dsu d(m);
    rep(i,0,n){
        //頂点番号の取得
        int u = mp[s[i]];
        int v = mp[t[i]];
        //すでにサイクルが形成されていればアウト
        if (d.same(u, v)){
            cout << "No" << endl;
            return 0;
        }
        //基本的に頂点をつなげるスタイル
        d.merge(u, v);
    }
    cout << "Yes" << endl;
    return 0;
}

image.png
解けました!

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?