結果
問題 | No.1320 Two Type Min Cost Cycle |
ユーザー |
|
提出日時 | 2020-12-02 20:54:20 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
CE
(最新)
AC
(最初)
|
実行時間 | - |
コード長 | 7,869 bytes |
コンパイル時間 | 535 ms |
コンパイル使用メモリ | 85,656 KB |
最終ジャッジ日時 | 2025-01-16 13:33:20 |
ジャッジサーバーID (参考情報) |
judge3 / judge3 |
(要ログイン)
コンパイルエラー時のメッセージ・ソースコードは、提出者また管理者しか表示できないようにしております。(リジャッジ後のコンパイルエラーは公開されます)
ただし、clay言語の場合は開発者のデバッグのため、公開されます。
ただし、clay言語の場合は開発者のデバッグのため、公開されます。
コンパイルメッセージ
main.cpp: In instantiation of ‘class RadixHeap<int>’: main.cpp:105:10: required from here main.cpp:17:36: error: ‘RadixHeap<T>::vq’ has incomplete type 17 | array<vector<TypeNode>,65> vq; | ^~ In file included from /usr/include/c++/13/bits/memory_resource.h:47, from /usr/include/c++/13/string:58, from /usr/include/c++/13/bits/locale_classes.h:40, from /usr/include/c++/13/bits/ios_base.h:41, from /usr/include/c++/13/ios:44, from /usr/include/c++/13/ostream:40, from /usr/include/c++/13/iostream:41, from main.cpp:1: /usr/include/c++/13/tuple:2019:45: note: declaration of ‘struct std::array<std::vector<std::pair<long long unsigned int, int>, std::allocator<std::pair<long long unsigned int, int> > >, 65>’ 2019 | template<typename _Tp, size_t _Nm> struct array; | ^~~~~ main.cpp: In function ‘int main()’: main.cpp:237:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 237 | scanf("%d",&T); | ~~~~~^~~~~~~~~ main.cpp:238:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 238 | scanf("%d%d",&N,&M); | ~~~~~^~~~~~~~~~~~~~ main.cpp:242:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 242 | scanf("%d%d%d",&u,&v,&w); | ~~~~~^~~~~~~~~~~~~~~~~~~
ソースコード
#include <iostream> #include <vector> #include <cassert> #include <queue> #include <stack> #include <set> #include <algorithm> #include <map> using namespace std; /* * @title RadixHeap - 64bit型非負整数heap * @docs md/heap/RadixHeap.md */ template<class T> class RadixHeap{ using TypeNode = pair<unsigned long long, T>; array<vector<TypeNode>,65> vq; unsigned long long size_num; TypeNode last; inline int bit(unsigned long long a) { return a ? 64 - __builtin_clzll(a) : 0; } public: RadixHeap(T mini) : size_num(0), last(make_pair(0,mini)) { // do nothing } inline bool empty() { return size_num == 0; } inline size_t size(){ return size_num; } inline void push(TypeNode x){ ++size_num; vq[bit(x.first^last.first)].push_back(x); } inline void emplace(unsigned long long key,T val){ ++size_num; vq[bit(key^last.first)].emplace_back(key,val); } inline TypeNode pop() { if(vq[0].empty()) { int i = 1; while(vq[i].empty()) ++i; last = *min_element(vq[i].begin(),vq[i].end()); for(auto &p : vq[i]) vq[bit(p.first ^ last.first)].push_back(p); vq[i].clear(); } --size_num; auto res = vq[0].back(); vq[0].pop_back(); return res; } }; /* * @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; RadixHeap<int> q(0); q.push({0,root}); dist[root] = 0; while (q.size()) { auto top = q.pop(); size_t curr = top.second; 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() { RadixHeap<int> q(0); q.push({0,root}); dist[root] = 0; while (q.size()) { auto top = q.pop(); size_t curr = top.second; 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); }