結果
| 問題 |
No.1320 Two Type Min Cost Cycle
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-12-03 00:21:05 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 414 ms / 2,000 ms |
| コード長 | 6,996 bytes |
| コンパイル時間 | 1,611 ms |
| コンパイル使用メモリ | 102,476 KB |
| 最終ジャッジ日時 | 2025-01-16 13:40:09 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 57 |
コンパイルメッセージ
main.cpp: In function ‘int main()’:
main.cpp:194:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
194 | scanf("%d",&T);
| ~~~~~^~~~~~~~~
main.cpp:195:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
195 | scanf("%d%d",&N,&M);
| ~~~~~^~~~~~~~~~~~~~
main.cpp:199:14: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
199 | 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 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;
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;
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);
}