제출 #1316850

#제출 시각아이디문제언어결과실행 시간메모리
1316850WH8Olympic Bus (JOI20_ho_t4)C++17
0 / 100
178 ms8320 KiB
#include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; #include <bits/stdc++.h> using namespace std; #define int long long #define pll pair<long long, long long> #define mp make_pair #define pb push_back #define f first #define s second #define endl '\n' #define ld long double #define sz(x) static_cast<int>((x).size()) #define i5 tuple<int,int,int,int,int> #define all(x) x.begin(), x.end() #define iiii tuple<int, int,int,int> #define ld long double #define lol pair<pll,pll> #define iii tuple<int,int,int> #define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> int n,m; vector<vector<iii>> al(205), tal(205); vector<tuple<int,int,int,int>> ed; pair<vector<int>, vector<int>> dijk(int s, int skip, vector<vector<iii>> & aa){ vector<int> pdist(n+1, 1e15), dist(n+1, 1e15), from(n+1, -1), ways(n+1, 0); pdist[s]=0; ways[s]=1; for(int i=0;i<n;i++){ pll mn=mp((int)1e16,0); for(int i=1;i<=n;i++){ mn=min(mn, mp(pdist[i], i)); } //printf("relaxing %lld, %lld\n", mn.f, mn.s); if (dist[mn.s] < pdist[mn.s]) continue; dist[mn.s]=pdist[mn.s]; //for(int j=1;j<=n;j++){cout<<dist[j]<<" ";} cout<<endl; pdist[mn.s]=1e15; int d=dist[mn.s], c=mn.s; for(auto [to,w,ind]:aa[c]){ if(dist[to]<d+w or pdist[to]<d+w or ind==skip)continue; if(dist[to] > d+w and pdist[to] > d+w){ assert(dist[to] == 1e15); pdist[to]=d+w; from[to]=ind; } } } return mp(dist, from); } signed main(){ cin>>n>>m; for(int i=0;i<m;i++){ int a,b,c,d;cin>>a>>b>>c>>d; ed.pb({a,b,c,d}); al[a].pb({b,c,i}); tal[b].pb({a,c,i}); } vector<vector<int>> anw(m+1), bnw(m+1); auto [an, af] = dijk(1, m, al); auto [at, atf] = dijk(1, m, tal); auto [bn, bf] = dijk(n, m, al); auto [bt, btf] = dijk(n, m, tal); vector<bool> ona(m+1, 0), onb(m+1, 0); /*for(int i=1;i<=n;i++){ printf("dist from 1 of i %lld is %lld,from %lld\n", i, an[i], af[i]); printf("dist from n of i %lld is %lld, from %lld\n", i, bn[i], bf[i]); }*/ int cnt=0; int ce=af[n]; while(ce != -1){ //if(cnt++ > 5)return 0; //printf("an, path ce %lld\n", ce); ona[ce]=true; ce = af[get<0>(ed[ce])]; } ce=bf[1]; while(ce != -1){ onb[ce]=true; ce = bf[get<0>(ed[ce])]; } int ans=an[n] + bn[1]; for(int i=0;i<m;i++){ auto [a,b,c,d]=ed[i]; // a --> b now b-->a //printf("edge %lld, ans %lld\n", i,ans); // if on the shortest path of 1->n or n->1, rerun the dijkstra without the edge, at most 2*n. int ab=0,ba=0; if(ona[i] or onb[i]){ ab=dijk(1, i, al).f[n], ba=dijk(n, i, al).f[1]; //printf("on a or b ab %lld, ba %lld\n", ab, ba); ans=min(ans, ba+ab); } else { // we (force to go through b->a, without travelling on a->b) or (dont go through b->a :then its just an[n] or bn[1]). if (af[b] == i){ auto [nn, _] = dijk(1, i, al); ab+=nn[b]; } else ab+=an[b]; if (btf[a] == i){ auto [nn, _] = dijk(n, i, tal); ab += nn[a]; } else ab+=bt[a]; if (bf[b] == i){ auto [nn, _] = dijk(n, i, al); ba += nn[b]; } else ba += bn[b]; if(atf[a] == i){ auto [nn, _] = dijk(1, i, tal); ba += nn[a]; } else ba += at[a]; ans=min({ans, an[n] + bn[1], min(an[n], ab+c)+min(bn[1], ba+c)+d}); //printf("not on a or b, ab %lld, ba %lld\n",ab,ba); } } cout<<(ans > 1e14? -1 : ans); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...