結果

問題 No.1983 [Cherry 4th Tune C] 南の島のマーメイド
ユーザー 👑 NachiaNachia
提出日時 2022-06-17 21:52:16
言語 C++17
(gcc 13.2.0 + boost 1.83.0)
結果
CE  
(最新)
AC  
(最初)
実行時間 -
コード長 10,980 bytes
コンパイル時間 904 ms
コンパイル使用メモリ 78,564 KB
最終ジャッジ日時 2024-04-17 13:37:16
合計ジャッジ時間 2,695 ms
ジャッジサーバーID
(参考情報)
judge4 / judge2
このコードへのチャレンジ(β)
コンパイルエラー時のメッセージ・ソースコードは、提出者また管理者しか表示できないようにしております。(リジャッジ後のコンパイルエラーは公開されます)
ただし、clay言語の場合は開発者のデバッグのため、公開されます。

コンパイルメッセージ
main.cpp:304:13: error: 'uint32_t' does not name a type
  304 | using u32 = uint32_t;
      |             ^~~~~~~~
main.cpp:300:1: note: 'uint32_t' is defined in header '<cstdint>'; did you forget to '#include <cstdint>'?
  299 | #include <atcoder/modint>
  +++ |+#include <cstdint>
  300 | 
main.cpp:306:13: error: 'uint64_t' does not name a type
  306 | using u64 = uint64_t;
      |             ^~~~~~~~
main.cpp:306:13: note: 'uint64_t' is defined in header '<cstdint>'; did you forget to '#include <cstdint>'?

ソースコード

diff #



#include <vector>
#include <utility>

namespace nachia{
    
struct AdjacencyList{
public:
    struct AdjacencyListRange{
        using iterator = typename std::vector<int>::const_iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        const int& operator[](int i) const { return begi[i]; }
    };
private:
    int mn;
    std::vector<int> E;
    std::vector<int> I;
public:
    AdjacencyList(int n, std::vector<std::pair<int,int>> edges, bool rev){
        mn = n;
        std::vector<int> buf(n+1, 0);
        for(auto [u,v] : edges){ ++buf[u]; if(rev) ++buf[v]; }
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        E.resize(buf[n]);
        for(int i=(int)edges.size()-1; i>=0; i--){
            auto [u,v] = edges[i];
            E[--buf[u]] = v;
            if(rev) E[--buf[v]] = u;
        }
        I = std::move(buf);
    }
    AdjacencyList(const std::vector<std::vector<int>>& edges = {}){
        int n = mn = edges.size();
        std::vector<int> buf(n+1, 0);
        for(int i=0; i<n; i++) buf[i+1] = buf[i] + edges[i].size();
        E.resize(buf[n]);
        for(int i=0; i<n; i++) for(int j=0; j<(int)edges[i].size(); j++) E[buf[i]+j] = edges[i][j];
        I = std::move(buf);
    }
    static AdjacencyList from_raw(std::vector<int> targets, std::vector<int> bounds){
        AdjacencyList res;
        res.mn = bounds.size() - 1;
        res.E = std::move(targets);
        res.I = std::move(bounds);
        return res;
    }
    AdjacencyListRange operator[](int u) const {
        return AdjacencyListRange{ E.begin() + I[u], E.begin() + I[u+1] };
    }
    int num_vertices() const { return mn; }
    int size() const { return num_vertices(); }
    int num_edges() const { return E.size(); }
    AdjacencyList reversed_edges() const {
        AdjacencyList res;
        int n = res.mn = mn;
        std::vector<int> buf(n+1, 0);
        for(int v : E) ++buf[v];
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        res.E.resize(buf[n]);
        for(int u=0; u<n; u++) for(int v : operator[](u)) res.E[--buf[v]] = u;
        res.I = std::move(buf);
        return res;
    }
};

struct AdjacencyListEdgeIndexed{
public:
    struct Edge { int to; int edgeidx; };
    struct AdjacencyListRange{
        using iterator = typename std::vector<Edge>::const_iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        const Edge& operator[](int i) const { return begi[i]; }
    };
private:
    int mn;
    std::vector<Edge> E;
    std::vector<int> I;
public:
    AdjacencyListEdgeIndexed(int n, const std::vector<std::pair<int,int>>& edges, bool rev){
        mn = n;
        std::vector<int> buf(n+1, 0);
        for(auto [u,v] : edges){ ++buf[u]; if(rev) ++buf[v]; }
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        E.resize(buf[n]);
        for(int i=(int)edges.size()-1; i>=0; i--){
            auto [u,v] = edges[i];
            E[--buf[u]] = { v, i };
            if(rev) E[--buf[v]] = { u, i };
        }
        I = std::move(buf);
    }
    AdjacencyListEdgeIndexed() : AdjacencyListEdgeIndexed(0, {}, false) {}
    AdjacencyListRange operator[](int u) const {
        return AdjacencyListRange{ E.begin() + I[u], E.begin() + I[u+1] };
    }
    int num_vertices() const { return mn; }
    int size() const { return num_vertices(); }
    int num_edges() const { return E.size(); }
    AdjacencyListEdgeIndexed reversed_edges() const {
        AdjacencyListEdgeIndexed res;
        int n = res.mn = mn;
        std::vector<int> buf(n+1, 0);
        for(auto [v,i] : E) ++buf[v];
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        res.E.resize(buf[n]);
        for(int u=0; u<n; u++) for(auto [v,i] : operator[](u)) res.E[--buf[v]] = {u,i};
        res.I = std::move(buf);
        return res;
    }
};

} // namespace nachia


namespace nachia{

class BiconnectedComponents{
private:
    int mn;
    int mm;
    int mnum_bcs;
    ::std::vector<::std::pair<int, int>> medges;
    ::std::vector<int> edgeidx_to_bcidx;
public:
    BiconnectedComponents(int n, ::std::vector<::std::pair<int, int>> edges){

		// after dfs1 ... inverse of dfsi_to_vtx
        ::std::vector<int> vtx_to_dfsi;
		// not visited by dfs1 ... -1
		// visited by dfs1 ... (the parent of parent of v and v would be cut when we delete the parent of v) ? 1 : 0
        ::std::vector<int> linked_over;
		// not visited by dfs1 ... -1
		// visited by dfs1 and no parent in the dfs tree ... -2
		// otherwise ... the parent edge
        ::std::vector<int> dfs_parent;
        // parent vtx
        ::std::vector<int> dfs_parentp;
        ::std::vector<int> dfs_backedge;

        mn = n;
        int m = edges.size();
        medges = std::move(edges);
        AdjacencyListEdgeIndexed adj(n, medges, true);
        vtx_to_dfsi.resize(n);
        dfs_parent.assign(n, -1);
        dfs_parentp.assign(n, -1);
        dfs_backedge.assign(n, -1);
        int dfsi = 0;
        
        int num_bcs = 0;
        ::std::vector<int> res(m);

        ::std::vector<int> mem(n*2);
        int memi = 0;

        for(int i=0; i<n; i++) if(dfs_parent[i] == -1){ // for each component
            dfs_parent[i] = -2;
            mem[memi++] = i; mem[memi++] = 0; // (p, ei)
            while(memi){
                int ei = mem[--memi];
                int p = mem[--memi];
                if(ei == 0){
                    vtx_to_dfsi[p] = dfsi;
                    dfs_backedge[p] = dfsi;
                    dfsi++;
                }
                while(true){
                    if(ei == adj[p].size()){
                        if(0 <= dfs_parentp[p]){
                            dfs_backedge[dfs_parentp[p]] = ::std::min(dfs_backedge[dfs_parentp[p]], dfs_backedge[p]);
                        }
                        break;
                    }
                    auto [nx,i] = adj[p][ei++];
                    if(dfs_parent[nx] != -1){
                        // backedges and multiedges
                        dfs_backedge[p] = ::std::min(dfs_backedge[p], vtx_to_dfsi[nx]);
                    }
                    else{
                        // along dfs tree
                        dfs_parent[nx] = i;
                        dfs_parentp[nx] = p;
                        memi++; mem[memi++] = ei;
                        mem[memi++] = nx; mem[memi++] = 0;
                        break;
                    }
                }
            }
        }

        for(int i=0; i<n; i++) if(dfs_parent[i] < 0){
            mem[memi++] = i;
            while(memi){
                int p = mem[--memi];
                if(dfs_parent[p] < 0){
                    // different child is in different block
                    for(auto [nx,i] : adj[p]) if(dfs_parent[nx] == i){
                        mem[memi++] = nx; dfs_backedge[nx] = num_bcs++;
                    }
                    continue;
                }
                for(auto [nx,i] : adj[p]){
                    if(dfs_parent[nx] != i){
                        // backedges and multiedges
                        res[i] = dfs_backedge[p];
                    }
                    else{
                        // along dfs tree
                        mem[memi++] = nx;
                        bool linked_over = dfs_backedge[nx] < vtx_to_dfsi[p];
                        dfs_backedge[nx] = linked_over ? dfs_backedge[p] : num_bcs++; // not linked over -> cut
                    }
                }
            }
        }

        edgeidx_to_bcidx = ::std::move(res);
        mm = m;
        mnum_bcs = num_bcs;
    }

    int get_num_bcts() const { return mnum_bcs; }

    ::std::vector<::std::vector<int>> get_bcs() const {
        ::std::vector<::std::vector<int>> res(mnum_bcs);
        for(int i=0; i<mm; i++){
            res[edgeidx_to_bcidx[i]].push_back(i);
        }
        return res;
    }

    AdjacencyList get_bct() const {
        int bct_n = mn + mnum_bcs;
        AdjacencyList bc_edgelists; {
            ::std::vector<int> buf(mnum_bcs+1);
            for(int bci : edgeidx_to_bcidx) ++buf[bci];
            for(int i=1; i<=mnum_bcs; i++) buf[i] += buf[i-1];
            ::std::vector<int> E(buf.back());
            for(int i=0; i<mm; i++) E[--buf[edgeidx_to_bcidx[i]]] = i;
            bc_edgelists = AdjacencyList::from_raw(::std::move(E), ::std::move(buf));
        }
        ::std::vector<::std::pair<int, int>> res(bct_n - 1);
        int resi = 0;
        ::std::vector<int> visited(mn);
        for(int bci=0; bci<mnum_bcs; bci++){
            for(int e : bc_edgelists[bci]){
                auto [u,v] = medges[e];
                if(!visited[u]){ visited[u] = 1; res[resi++] = {mn+bci,u}; }
                if(!visited[v]){ visited[v] = 1; res[resi++] = {mn+bci,v}; }
            }
            for(int e : bc_edgelists[bci]){
                auto [u,v] = medges[e];
                visited[u] = visited[v] = 0;
            }
        }
        return AdjacencyList(bct_n, res, true);
    }
};

} // namespace nachia

#include <algorithm>


namespace nachia {
    struct Dsu{
    private:
        std::vector<int> w;
    public:
        Dsu(int n) : w(n, -1) {}
        int leader(int u){
            if(w[u] < 0) return u;
            return w[u] = leader(w[u]);
        }
        int merge(int u, int v){
            u = leader(u);
            v = leader(v);
            if(-w[u] < -w[v]) std::swap(u, v);
            else if(w[u] == w[v]) w[u]--;
            w[v] = u;
            return u;
        }
        bool same(int u, int v){
            return leader(u) == leader(v);
        }
    };
} // namespace nachia

#include <iostream>
#include <string>
#include <atcoder/modint>


using namespace std;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;
#define rep(i,n) for(int i=0; i<(int)(n); i++)


const i64 INF = 1001001001001001001;
using modint = atcoder::static_modint<1000000007>;



int main(){
    int N; cin >> N;
    int M; cin >> M;
    int Q; cin >> Q;
    vector<pair<int,int>> edges(M);
    rep(i,M){
        int u; cin >> u; u--;
        int v; cin >> v; v--;
        edges[i] = make_pair(u,v);
    }

    auto bcs = nachia::BiconnectedComponents(N, edges);

    vector<pair<int,int>> new_edges;
    for(auto& bc : bcs.get_bcs()) if(bc.size() == 1) new_edges.push_back(edges[bc[0]]);

    nachia::Dsu dsu(N);
    for(auto [u,v] : new_edges) dsu.merge(u,v);

    rep(i,Q){
        int u; cin >> u; u--;
        int v; cin >> v; v--;
        bool ans = dsu.same(u,v);
        cout << (ans ? "Yes\n" : "No\n");
    }
    return 0;
}


struct ios_do_not_sync{
    ios_do_not_sync(){
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
    }
} ios_do_not_sync_instance;


0