結果
問題 | No.1320 Two Type Min Cost Cycle |
ユーザー | maspy |
提出日時 | 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 |
ソースコード
#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); }