結果

問題 No.1813 Magical Stones
ユーザー se1ka2se1ka2
提出日時 2022-01-14 23:11:44
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 6,279 bytes
コンパイル時間 1,798 ms
コンパイル使用メモリ 109,388 KB
実行使用メモリ 28,492 KB
最終ジャッジ日時 2023-08-12 22:03:19
合計ジャッジ時間 8,709 ms
ジャッジサーバーID
(参考情報)
judge8 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,380 KB
testcase_01 AC 1 ms
4,384 KB
testcase_02 AC 1 ms
4,384 KB
testcase_03 AC 35 ms
28,492 KB
testcase_04 AC 1 ms
4,384 KB
testcase_05 AC 2 ms
4,380 KB
testcase_06 WA -
testcase_07 AC 2 ms
4,380 KB
testcase_08 WA -
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 AC 36 ms
28,400 KB
testcase_15 WA -
testcase_16 WA -
testcase_17 AC 230 ms
18,228 KB
testcase_18 WA -
testcase_19 WA -
testcase_20 WA -
testcase_21 WA -
testcase_22 WA -
testcase_23 WA -
testcase_24 WA -
testcase_25 WA -
testcase_26 WA -
testcase_27 WA -
testcase_28 WA -
testcase_29 WA -
testcase_30 WA -
testcase_31 WA -
testcase_32 AC 1 ms
4,384 KB
testcase_33 AC 1 ms
4,384 KB
testcase_34 WA -
testcase_35 AC 20 ms
4,384 KB
testcase_36 WA -
testcase_37 WA -
testcase_38 WA -
testcase_39 WA -
testcase_40 WA -
testcase_41 AC 7 ms
4,380 KB
testcase_42 AC 21 ms
4,380 KB
testcase_43 WA -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <queue>
#include <map>
using namespace std;

struct Graph
{
    int n;
    std::vector<std::vector<int>> g;
    
    Graph(){}
    
    Graph(int n) : n(n){
        g.resize(n);
    }
    
    void add_edge(int from, int to){
        g[from].push_back(to);
    }
};

struct SCC      //StronglyConnectedComponents
{
    int n;
    int k;
    std::vector<std::vector<int>> g, rg;
    std::vector<bool> used;
    std::vector<int> cmp;
    std::vector<int> vs;
    
    SCC(){}
    
    SCC(int n) : n(n){
        g.resize(n);
        rg.resize(n);
        used.resize(n);
        cmp.resize(n);
    }
    
    void add_edge(int from, int to){
        g[from].push_back(to);
        rg[to].push_back(from);
    }
    
    void dfs(int u){
        used[u] = true;
        for(int v : g[u]){
            if(!used[v]) dfs(v);
        }
        vs.push_back(u);
    }
    
    void rdfs(int u, int k){
        used[u] = true;
        cmp[u] = k;
        for(int v : rg[u]){
            if(!used[v]) rdfs(v, k);
        }
    }
    
    int decomposition(){
        for(int i = 0; i < n; i++) used[i] = false;
        for(int i = 0; i < n; i++){
            if(!used[i]) dfs(i);
        }
        for(int i = 0; i < n; i++) used[i] = false;
        k = 0;
        for(int i = n - 1; i >= 0; i--){
            if(!used[vs[i]]){
                rdfs(vs[i], k);
                k++;
            }
        }
        return k;
    }
    
    int decomposition(Graph &dag){
        k = decomposition();
        dag.n = k;
        dag.g.resize(k);
        std::map<std::pair<int, int>, bool> mp;
        for(int u = 0; u < n; u++){
            for(int v : g[u]){
                if(!mp[std::pair<int, int> (cmp[u], cmp[v])] && cmp[u] != cmp[v]){
                    mp[std::pair<int, int> (cmp[u], cmp[v])] = true;
                    dag.add_edge(cmp[u], cmp[v]);
                }
            }
        }
        return k;
    }
};

template <typename T>
struct Edge
{
    int to;
    T cap;
    int rev;
    int id;
};

template <typename T>
struct Flow
{
    int n;
    int source;
    int sink;
    T current_flow;
    std::vector<int> d;
    std::vector<int> nx;
    std::vector<std::vector<Edge<T>>> g;
    std::vector<std::pair<int, int>> epos;
    
    Flow(){}
    
    Flow(int n, int source, int sink) : n(n), source(source), sink(sink), current_flow(0){
        d.resize(n);
        nx.resize(n);
        g.resize(n);
    }
    
    void add_edge(int from, int to, T cap){
        epos.push_back(std::pair<int, int>(from, (int)g[from].size()));
        g[from].push_back((Edge<T>){to, cap, (int)g[to].size(), (int)epos.size() - 1});
        g[to].push_back((Edge<T>){from, 0, (int)g[from].size() - 1, -1});
    }
    
    T delete_edge(int id){
        Edge<T> &e = g[epos[id].first][epos[id].second];
        Edge<T> &re = g[e.to][e.rev];
        int u = re.to, v = e.to;
        T delete_f = re.cap;
        e.cap = 0;
        re.cap = 0;
        T reverse_f = delete_f - add_flow(u, v, delete_f);
        add_flow(u, source, reverse_f);
        add_flow(sink, v, reverse_f);
        current_flow -= reverse_f;
        return current_flow;
    }
    
    void bfs(int s){
        fill(d.begin(), d.end(), -1);
        std::queue<int> que;
        d[s] = 0;
        que.push(s);
        while(que.size()){
            int u = que.front();
            que.pop();
            for(Edge<T> &e : g[u]){
                int v = e.to;
                Edge<T> &re = g[v][e.rev];
                if(re.cap > 0 && d[v] == -1){
                    d[v] = d[u] + 1;
                    que.push(v);
                }
            }
        }
    }
    
    T dfs(int u, int s, T f){
        if(u == s) return f;
        for(int &i = nx[u]; i < (int)g[u].size(); i++){
            Edge<T> &e = g[u][i];
            int v = e.to;
            if(d[v] >= d[u] || e.cap == 0) continue;
            if(f == -1) f = e.cap;
            else f = std::min(f, e.cap);
            T fl = dfs(v, s, f);
            if(fl > 0){
                e.cap -= fl;
                g[e.to][e.rev].cap += fl;
                return fl;
            }
        }
        return 0;
    }
    
    T add_flow(int r, int s, T max_f){
        T res = 0;
        while(true){
            if(max_f == 0) return res;
            bfs(s);
            if(d[r] == -1) return res;
            for(int i = 0; i < n; i++) nx[i] = 0;
            for(T f; (f = dfs(r, s, max_f)) > 0;){
                res += f;
                if(max_f != -1) max_f -= f;
            }
        }
    }
    
    T max_flow(T max_f = -1){
        if(max_f != -1){
            max_f -= current_flow;
            if(max_f < 0){
                current_flow -= add_flow(sink, source, -max_f);
                return current_flow;
            }
        }
        current_flow += add_flow(source, sink, max_f);
        return current_flow;
    }
    
    int get_flow(int id){
        Edge<T> &e = g[epos[id].first][epos[id].second];
        Edge<T> &re = g[e.to][e.rev];
        return re.cap;
    }
};

struct BipartiteMatching
{
    int p;
    int q;
    Flow<int> g;
    
    BipartiteMatching(){}
    
    BipartiteMatching(int p, int q) : p(p), q(q){
        g.n = p + q + 2;
        g.source = p + q;
        g.sink = p + q + 1;
        g.current_flow = 0;
        g.d.resize(g.n);
        g.nx.resize(g.n);
        g.g.resize(g.n);
        for(int i = 0; i < p; i++) g.add_edge(p + q, i, 1);
        for(int i = p; i < p + q; i++) g.add_edge(i, p + q + 1, 1);
    }
    
    void add_edge(int u, int v){
        g.add_edge(u, v + p, 1);
    }
    
    int delete_edge(int id){
        return g.delete_edge(id + p + q);
    }
    
    int max_matching(){
        return g.max_flow();
    }
    
    bool is_used(int id){
        return g.get_flow(id + p + q);
    }
};

int main()
{
    int n, m;
    cin >> n >> m;
    SCC g(n);
    for(int i = 0; i < m; i++){
        int a, b;
        cin >> a >> b;
        a--; b--;
        g.add_edge(a, b);
    }
    Graph h;
    int k = g.decomposition(h);
    if(k == 1){
        cout << 0 << endl;
        return 0;
    }
    BipartiteMatching M(k, k);
    for(int u = 0; u < k; u++){
        for(int v : h.g[u]) M.add_edge(u, v);
    }
    cout << k - M.max_matching() << endl;
}
0