Submission #1293163

#TimeUsernameProblemLanguageResultExecution timeMemory
1293163TymondOlympic Bus (JOI20_ho_t4)C++20
100 / 100
89 ms2116 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; using ld = long double; #define fi first #define se second #define vi vector<int> #define vll vector<long long> #define pii pair<int, int> #define pll pair<long long, long long> #define pb push_back #define mp make_pair #define eb emplace_back #define all(x) (x).begin(), (x).end() #define sz(x) (int)(x).size() mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); mt19937_64 rng64(chrono::high_resolution_clock::now().time_since_epoch().count()); inline int rand(int l,int r){return uniform_int_distribution<int>(l, r)(rng);} inline ll rand(ll l,ll r){return uniform_int_distribution<ll>(l, r)(rng64);} #ifdef DEBUG auto&operator<<(auto&o,pair<auto,auto>p){return o<<"("<<p.first<<", "<<p.second<<")";} auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<<e;return o<<"}";} #define debug(X...)cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(X) #else #define debug(...){} #endif struct custom_hash { static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } }; struct pair_hash{ size_t operator()(const pair<int,int>&x)const{ return hash<long long>()(((long long)x.first)^(((long long)x.second)<<32)); } }; struct Edge{ int v, u, c, d; Edge(){ v = u = c = d = 0; } Edge(int v1, int u1, int c1, int d1){ v = v1; u = u1; c = c1; d = d1; } }; const int MAXN = 207; const int MAXM = 5e4 + 7; const ll INF = 2e9; vi g[2][MAXN]; ll dist[2][2][MAXN]; int back[2][2][MAXN]; Edge edges[MAXM]; int used[MAXN]; int n, m; int special[MAXM]; void Dijkstra(int cur, int st){ int start = (n - 1) * st + 1; for(int i = 1; i <= n; i++){ dist[cur][st][i] = INF; back[cur][st][i] = 0; used[i] = 0; } dist[cur][st][start] = 0LL; dist[cur][st][0] = INF; int gId = (cur & 1); if(gId){ for(int i = 1; i <= m; i++){ swap(edges[i].u, edges[i].v); } } for(int k = 1; k <= n; k++){ int best = 0; for(int i = 1; i <= n; i++){ if(!used[i] && dist[cur][st][i] < dist[cur][st][best]){ best = i; } } if(dist[cur][st][best] >= INF){ break; } used[best] = 1; for(auto& e : g[gId][best]){ if(dist[cur][st][edges[e].u] > dist[cur][st][best] + edges[e].c){ dist[cur][st][edges[e].u] = dist[cur][st][best] + edges[e].c; back[cur][st][edges[e].u] = e; } } } int curr = n + 1 - start; while(curr){ //cerr << curr << ' ' << back[cur][st][curr] << '\n'; // cerr << edges[back[cur][st][curr]].v << '\n'; special[back[cur][st][curr]] = 1; curr = edges[back[cur][st][curr]].v; } // debug(f); if(gId){ for(int i = 1; i <= m; i++){ swap(edges[i].u, edges[i].v); } } } int Dijkstra2(int start, int finish){ vi dist2(n + 1, INF); dist2[start] = 0; for(int i = 1; i <= n; i++){ used[i] = 0; } int best; for(int k = 1; k <= n; k++){ best = 0; for(int i = 1; i <= n; i++){ if(!used[i] && dist2[i] < dist2[best]){ best = i; } } if(dist2[best] >= INF){ break; } used[best] = 1; for(auto& e : g[0][best]){ dist2[edges[e].u] = min(dist2[edges[e].u], dist2[best] + edges[e].c); } } return dist2[finish]; } int main(){ ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL); cin >> n >> m; for(int i = 1; i <= m; i++){ int a, b, c, d; cin >> a >> b >> c >> d; g[0][a].pb(i); g[1][b].pb(i); edges[i] = Edge(a, b, c, d); } Dijkstra(0, 0); Dijkstra(0, 1); Dijkstra(1, 0); Dijkstra(1, 1); ll ans = (ll)dist[0][0][n] + dist[0][1][1]; for(int i = 1; i <= m; i++){ //cerr << "------\n"; if(special[i]){ // cerr << "SPECIAL: " << i << '\n'; g[0][edges[i].v].erase(find(all(g[0][edges[i].v]), i)); g[0][edges[i].u].pb(i); swap(edges[i].v, edges[i].u); //cerr << Dijkstra2(1, n) << '\n'; // cerr << Dijkstra2(n, 1) << '\n'; ll now = (ll)Dijkstra2(1, n) + Dijkstra2(n, 1) + edges[i].d; g[0][edges[i].v].erase(find(all(g[0][edges[i].v]), i)); g[0][edges[i].u].pb(i); swap(edges[i].v, edges[i].u); ans = min(ans, now); }else{ //cerr << dist[0][0][n] << '\n'; //cerr << dist[0][0][edges[i].u] << '\n'; //cerr << dist[1][1][edges[i].v] << '\n'; ll now = min(dist[0][0][n], (ll)dist[0][0][edges[i].u] + edges[i].c + dist[1][1][edges[i].v]) + edges[i].d; now += min(dist[0][1][1], (ll)dist[0][1][edges[i].u] + edges[i].c + dist[1][0][edges[i].v]); // cerr << min(dist[0][1][1], dist[0][1][edges[i].u] + edges[i].c + dist[1][0][edges[i].v]) << '\n'; // cerr << now << '\n'; ans = min(ans, now); } } if(ans >= INF){ cout << "-1\n"; }else{ cout << ans << '\n'; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...