結果

問題 No.1320 Two Type Min Cost Cycle
ユーザー maspymaspy
提出日時 2020-12-11 20:07:08
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 628 ms / 2,000 ms
コード長 7,104 bytes
コンパイル時間 1,143 ms
コンパイル使用メモリ 102,272 KB
実行使用メモリ 6,948 KB
最終ジャッジ日時 2024-09-20 01:22:11
合計ジャッジ時間 6,857 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 1 ms
6,940 KB
testcase_02 AC 2 ms
6,940 KB
testcase_03 AC 2 ms
6,940 KB
testcase_04 AC 2 ms
6,944 KB
testcase_05 AC 3 ms
6,940 KB
testcase_06 AC 1 ms
6,948 KB
testcase_07 AC 5 ms
6,940 KB
testcase_08 AC 18 ms
6,944 KB
testcase_09 AC 274 ms
6,940 KB
testcase_10 AC 6 ms
6,940 KB
testcase_11 AC 189 ms
6,940 KB
testcase_12 AC 44 ms
6,940 KB
testcase_13 AC 110 ms
6,944 KB
testcase_14 AC 15 ms
6,940 KB
testcase_15 AC 6 ms
6,940 KB
testcase_16 AC 2 ms
6,940 KB
testcase_17 AC 4 ms
6,940 KB
testcase_18 AC 5 ms
6,940 KB
testcase_19 AC 48 ms
6,940 KB
testcase_20 AC 5 ms
6,940 KB
testcase_21 AC 170 ms
6,940 KB
testcase_22 AC 1 ms
6,940 KB
testcase_23 AC 2 ms
6,944 KB
testcase_24 AC 2 ms
6,940 KB
testcase_25 AC 2 ms
6,944 KB
testcase_26 AC 1 ms
6,940 KB
testcase_27 AC 2 ms
6,944 KB
testcase_28 AC 12 ms
6,940 KB
testcase_29 AC 72 ms
6,944 KB
testcase_30 AC 2 ms
6,944 KB
testcase_31 AC 13 ms
6,944 KB
testcase_32 AC 1 ms
6,940 KB
testcase_33 AC 101 ms
6,944 KB
testcase_34 AC 60 ms
6,944 KB
testcase_35 AC 3 ms
6,940 KB
testcase_36 AC 2 ms
6,944 KB
testcase_37 AC 2 ms
6,940 KB
testcase_38 AC 3 ms
6,940 KB
testcase_39 AC 2 ms
6,944 KB
testcase_40 AC 2 ms
6,940 KB
testcase_41 AC 2 ms
6,944 KB
testcase_42 AC 2 ms
6,940 KB
testcase_43 AC 7 ms
6,940 KB
testcase_44 AC 5 ms
6,940 KB
testcase_45 AC 346 ms
6,940 KB
testcase_46 AC 11 ms
6,940 KB
testcase_47 AC 88 ms
6,940 KB
testcase_48 AC 72 ms
6,944 KB
testcase_49 AC 9 ms
6,940 KB
testcase_50 AC 2 ms
6,940 KB
testcase_51 AC 2 ms
6,940 KB
testcase_52 AC 18 ms
6,940 KB
testcase_53 AC 9 ms
6,944 KB
testcase_54 AC 312 ms
6,940 KB
testcase_55 AC 312 ms
6,940 KB
testcase_56 AC 311 ms
6,944 KB
testcase_57 AC 616 ms
6,944 KB
testcase_58 AC 628 ms
6,940 KB
testcase_59 AC 606 ms
6,940 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <cassert>
#include <queue>
#include <stack>
#include <set>
#include <algorithm>
#include <map>
using namespace std;

/*
 * @title Graph
 * @docs md/graph/Graph.md
 */
template<class T> class Graph{
private:
    const size_t N,H,W;
public:
    vector<vector<pair<size_t,T>>> edges;
    Graph(const size_t N):H(-1),W(-1),N(N), edges(N) {}
    Graph(const size_t H, const size_t W):H(H),W(W),N(H*W), edges(H*W) {}
    inline void make_edge(size_t from, size_t to, T w) {
        edges[from].emplace_back(to,w);
    }
    //{from_y,from_x} -> {to_y,to_x} 
    inline void make_edge(pair<size_t,size_t> from, pair<size_t,size_t> to, T w) {
        make_edge(from.first*W+from.second,to.first*W+to.second,w);
    }
    inline void make_bidirectional_edge(size_t from, size_t to, T w) {
        make_edge(from,to,w);
        make_edge(to,from,w);
    }
    inline void make_bidirectional_edge(pair<size_t,size_t> from, pair<size_t,size_t> to, T w) {
        make_edge(from.first*W+from.second,to.first*W+to.second,w);
        make_edge(to.first*W+to.second,from.first*W+from.second,w);
    }
    inline size_t size(){return N;}
    inline size_t idx(pair<size_t,size_t> yx){return yx.first*W+yx.second;}
};

/*
 * @title MinimumDirectedClosedCircuit - 有向グラフの最小閉路検出
 * @docs md/graph/MinimumDirectedClosedCircuit.md
 */
template<class T> class MinimumDirectedClosedCircuit {
    //Tは整数型のみ
    static_assert(std::is_integral<T>::value, "template parameter T must be integral type");
    Graph<T>& graph;
    vector<T> dist;
    vector<int> parent;
    size_t N;
    T inf;
    int last,root;
private:

    T solve_impl() {
        T mini = inf;
        last = -1;
        using plli = pair<long long,int>;
        priority_queue<plli,vector<plli>,greater<plli>> q;
        q.push({0,root});
        dist[root] = 0;
        while (q.size()) {
            auto top = q.top();  q.pop();
            size_t curr = top.second;
            /*
            嘘dijkstra
            if(top.first > dist[curr]) continue;
            */
            for(auto& edge:graph.edges[curr]){
                size_t next = edge.first;
                T w  = edge.second;                
                if(dist[next] > dist[curr]+w) {
                    dist[next]   = dist[curr] + w;
                    parent[next] = curr;
                    q.push({dist[next],next});
                }
                //根に返って来てるなら閉路候補
                if(next == root && mini > dist[curr]+w) {
                    mini = dist[curr]+w;
                    last = curr;
                }                
            }
        }
        return mini;
    }
public:
    MinimumDirectedClosedCircuit(Graph<T>& graph, T inf)
     : graph(graph),N(graph.size()),dist(graph.size()),parent(graph.size()),inf(inf) {
    }
    //rootを含む最小閉路の集合を返す O(NlogN) 閉路がないときは空集合
    inline T solve(size_t rt){
        root = rt;
        //初期化
        for(int i = 0; i < N; ++i) dist[i] = inf, parent[i] = -1;
        //最小閉路の大きさを決める
        T mini = solve_impl();
        return mini;
    }
    vector<int> restore() {
        vector<int> res;
        if(last == -1) return res;
        int curr = last;
        res.push_back(curr);
        while(curr != root) res.push_back(curr = parent[curr]);
        reverse(res.begin(),res.end());
        return res;
    }
};

/*
 * @title MinimumUndirectedClosedCircuit - 無向グラフの最小閉路検出
 * @docs md/graph/MinimumUndirectedClosedCircuit.md
 */
template<class T> class MinimumUndirectedClosedCircuit {
    //Tは整数型のみ
    static_assert(std::is_integral<T>::value, "template parameter T must be integral type");
    Graph<T> graph;
    vector<T> dist;
    vector<int> parent,label;
    size_t N;
    T inf;
    int last_l,last_r,root;
private:
    void solve_impl() {
        using plli = pair<long long,int>;
        priority_queue<plli,vector<plli>,greater<plli>> q;
        q.push({0,root});
        dist[root] = 0;
        while (q.size()) {
            auto top = q.top(); q.pop();
            size_t curr = top.second;
            /*
            嘘dijkstra
            if(top.first > dist[curr]) continue;
            */
            for(auto& edge:graph.edges[curr]){
                size_t next = edge.first;
                T w  = edge.second;
                if(parent[curr] == next) continue;
                if(dist[next] > dist[curr] + w) {
                    dist[next]   = dist[curr] + w;
                    parent[next] = curr;
                    label[next]  = (curr==root?next:label[curr]);
                    q.push({dist[next],next});
                }
            }
        }
    }
    T solve_cycle() {
        T mini = inf;
        last_l=-1,last_r=-1;
        for(int l=0;l<N;++l) {
            if(l==root) continue;
            for(auto& edge:graph.edges[l]){
                int r = edge.first;
                T   w = edge.second;
                if(mini <= dist[l] + dist[r] + w) continue;
                if( (r==root && l!=label[l]) || (r!=root && label[l]!=label[r]) ) {
                    mini = dist[l] + dist[r] + w;
                    last_l = l;
                    last_r = r;
                }            
            }
        }
        return mini;
    }
public:
    MinimumUndirectedClosedCircuit(Graph<T>& graph, T inf)
     : graph(graph),N(graph.size()),dist(graph.size()),parent(graph.size()),label(graph.size()),inf(inf) {
    }
    //rootを含む最小閉路の集合を返す O(NlogN) 閉路がないときは空集合
    inline T solve(size_t rt){
        root = rt;
        //初期化
        for(int i = 0; i < N; ++i) dist[i] = inf, parent[i] = -1;
        solve_impl();
        T mini=solve_cycle();
        return mini;
    }
    //復元
    vector<int> restore() {
        stack<int> s;
        queue<int> q;
        vector<int> res;
        if(last_l != -1 && last_r != -1){
            for(int curr = last_l; curr != -1; curr = parent[curr]) s.push(curr);
            for(int curr = last_r; curr != root; curr = parent[curr]) q.push(curr);
            while(s.size()) res.push_back(s.top())  ,s.pop();
            while(q.size()) res.push_back(q.front()),q.pop();
        }
        return res;
    }
};

template <class T> void chmin(T& a, const T b){a=min(a,b);}

int main(void) {
    int T,N,M;
    scanf("%d",&T);
    scanf("%d%d",&N,&M);
    Graph<long long> graph(N);
    while(M--) {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        u--,v--;
        if(T) graph.make_edge(u,v,w);
        else  graph.make_bidirectional_edge(u,v,w);   
    }
    long long inf = 1e15;
    long long ans = inf;
    if(T) {
        MinimumDirectedClosedCircuit<long long> mdcc(graph,inf);
        for(int i=0;i<N;++i) chmin(ans,mdcc.solve(i));
    }
    else {
        MinimumUndirectedClosedCircuit<long long> mucc(graph,inf);
        for(int i=0;i<N;++i) chmin(ans,mucc.solve(i));
    }
    if(ans == inf) ans = -1;
    printf("%lld\n",ans);
}
0