結果
| 問題 |
No.1301 Strange Graph Shortest Path
|
| コンテスト | |
| ユーザー |
Hyado
|
| 提出日時 | 2020-11-27 23:13:43 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 357 ms / 3,000 ms |
| コード長 | 7,110 bytes |
| コンパイル時間 | 1,987 ms |
| コンパイル使用メモリ | 190,572 KB |
| 実行使用メモリ | 57,456 KB |
| 最終ジャッジ日時 | 2024-07-26 20:23:21 |
| 合計ジャッジ時間 | 12,539 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 33 |
ソースコード
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using db = double;
using ld = long double;
template<typename T> using V = vector<T>;
template<typename T> using VV = vector<vector<T>>;
#define fs first
#define sc second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(),(v).end()
#define siz(v) (ll)(v).size()
#define rep(i,a,n) for(ll i=a;i<(ll)(n);++i)
#define repr(i,a,n) for(ll i=n-1;(ll)a<=i;--i)
#define ENDL '\n'
typedef pair<int,int> Pi;
typedef pair<ll,ll> PL;
constexpr ll mod = 1000000007; // 998244353;
constexpr ll INF = 1000000099;
constexpr ll LINF = (ll)(1e18 +99);
const ld PI = acos((ld)-1);
const vector<ll> dx={-1,0,1,0},dy={0,1,0,-1};
template<typename T,typename U> inline bool chmin(T& t, const U& u){if(t>u){t=u;return 1;}return 0;}
template<typename T,typename U> inline bool chmax(T& t, const U& u){if(t<u){t=u;return 1;}return 0;}
template<typename T> inline T gcd(T a,T b){return b?gcd(b,a%b):a;}
inline void yes() { cout << "Yes" << ENDL; }
inline void no() { cout << "No" << ENDL; }
template<typename T,typename Y> inline T mpow(T a, Y n) {
T res = 1;
for(;n;n>>=1) {
if (n & 1) res = res * a;
a = a * a;
}
return res;
}
template <typename T> V<T> prefix_sum(const V<T>& v) {
int n = v.size();
V<T> ret(n + 1);
rep(i, 0, n) ret[i + 1] = ret[i] + v[i];
return ret;
}
template<typename T>
istream& operator >> (istream& is, vector<T>& vec){
for(auto&& x: vec) is >> x;
return is;
}
template<typename T,typename Y>
ostream& operator<<(ostream& os,const pair<T,Y>& p){
return os<<"{"<<p.fs<<","<<p.sc<<"}";
}
template<typename T> ostream& operator<<(ostream& os,const V<T>& v){
os<<"{";
for(auto e:v)os<<e<<",";
return os<<"}";
}
template<typename ...Args>
void debug(Args&... args){
for(auto const& x:{args...}){
cerr<<x<<' ';
}
cerr<<ENDL;
}
template <class Cap, class Cost> struct mcf_graph {
public:
mcf_graph() {}
mcf_graph(int n) : _n(n), g(n) {}
int add_edge(int from, int to, Cap cap, Cost cost) {
assert(0 <= from && from < _n);
assert(0 <= to && to < _n);
int m = int(pos.size());
pos.push_back({from, int(g[from].size())});
g[from].push_back(_edge{to, int(g[to].size()), cap, cost});
g[to].push_back(_edge{from, int(g[from].size()) - 1, 0, -cost});
return m;
}
struct edge {
int from, to;
Cap cap, flow;
Cost cost;
};
edge get_edge(int i) {
int m = int(pos.size());
assert(0 <= i && i < m);
auto _e = g[pos[i].first][pos[i].second];
auto _re = g[_e.to][_e.rev];
return edge{
pos[i].first, _e.to, _e.cap + _re.cap, _re.cap, _e.cost,
};
}
std::vector<edge> edges() {
int m = int(pos.size());
std::vector<edge> result(m);
for(int i = 0; i < m; i++) { result[i] = get_edge(i); }
return result;
}
std::pair<Cap, Cost> flow(int s, int t) {
return flow(s, t, std::numeric_limits<Cap>::max());
}
std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
return slope(s, t, flow_limit).back();
}
std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
return slope(s, t, std::numeric_limits<Cap>::max());
}
std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
assert(0 <= s && s < _n);
assert(0 <= t && t < _n);
assert(s != t);
// variants (C = maxcost):
// -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
// reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge
std::vector<Cost> dual(_n, 0), dist(_n);
std::vector<int> pv(_n), pe(_n);
std::vector<bool> vis(_n);
auto dual_ref = [&]() {
std::fill(dist.begin(), dist.end(), std::numeric_limits<Cost>::max());
std::fill(pv.begin(), pv.end(), -1);
std::fill(pe.begin(), pe.end(), -1);
std::fill(vis.begin(), vis.end(), false);
struct Q {
Cost key;
int to;
bool operator<(Q r) const { return key > r.key; }
};
std::priority_queue<Q> que;
dist[s] = 0;
que.push(Q{0, s});
while(!que.empty()) {
int v = que.top().to;
que.pop();
if(vis[v]) continue;
vis[v] = true;
if(v == t) break;
// dist[v] = shortest(s, v) + dual[s] - dual[v]
// dist[v] >= 0 (all reduced cost are positive)
// dist[v] <= (n-1)C
for(int i = 0; i < int(g[v].size()); i++) {
auto e = g[v][i];
if(vis[e.to] || !e.cap) continue;
// |-dual[e.to] + dual[v]| <= (n-1)C
// cost <= C - -(n-1)C + 0 = nC
Cost cost = e.cost - dual[e.to] + dual[v];
if(dist[e.to] - dist[v] > cost) {
dist[e.to] = dist[v] + cost;
pv[e.to] = v;
pe[e.to] = i;
que.push(Q{dist[e.to], e.to});
}
}
}
if(!vis[t]) { return false; }
for(int v = 0; v < _n; v++) {
if(!vis[v]) continue;
// dual[v] = dual[v] - dist[t] + dist[v]
// = dual[v] - (shortest(s, t) + dual[s] - dual[t]) +
// (shortest(s, v) + dual[s] - dual[v]) = - shortest(s, t) +
// dual[t] + shortest(s, v) = shortest(s, v) - shortest(s, t) >=
// 0 - (n-1)C
dual[v] -= dist[t] - dist[v];
}
return true;
};
Cap flow = 0;
Cost cost = 0, prev_cost = -1;
std::vector<std::pair<Cap, Cost>> result;
result.push_back({flow, cost});
while(flow < flow_limit) {
if(!dual_ref()) break;
Cap c = flow_limit - flow;
for(int v = t; v != s; v = pv[v]) {
c = std::min(c, g[pv[v]][pe[v]].cap);
}
for(int v = t; v != s; v = pv[v]) {
auto& e = g[pv[v]][pe[v]];
e.cap -= c;
g[v][e.rev].cap += c;
}
Cost d = -dual[s];
flow += c;
cost += c * d;
if(prev_cost == d) { result.pop_back(); }
result.push_back({flow, cost});
prev_cost = cost;
}
return result;
}
private:
int _n;
struct _edge {
int to, rev;
Cap cap;
Cost cost;
};
std::vector<std::pair<int, int>> pos;
std::vector<std::vector<_edge>> g;
};
signed main(){
cin.tie(0);cerr.tie(0);ios::sync_with_stdio(false);
cout<<fixed<<setprecision(20);
ll n,m;cin>>n>>m;
mcf_graph<ll,ll> mcf(n+2*(m+3));
int id=n;
rep(i,0,m){
int a,b,c,d;cin>>a>>b>>c>>d;
--a;--b;
mcf.add_edge(id,id+1,1,c);
mcf.add_edge(id,id+1,1,d);
mcf.add_edge(a,id,2,0);
mcf.add_edge(id+1,b,2,0);
mcf.add_edge(b,id,2,0);
mcf.add_edge(id+1,a,2,0);
id+=2;
}
cout<<mcf.flow(0,n-1,2).sc<<ENDL;
//auto es=mcf.edges();
//for(auto&& e:es)cout<<e.from<<" "<<e.to<<" "<<e.cost<<" "<<e.flow<<ENDL;
}
//! ( . _ . ) !
//CHECK overflow,vector_size,what to output?
//any other simpler approach?
//list all conditions, try mathematical and graphic observation
Hyado