#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, ways %lld, from %lld\n", i, at[i],aw[i], af[i]);
printf("dist from n of i %lld is %lld, ways %lld, from %lld\n", i, bt[i],bw[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
// 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], ab+ba+c});
printf("not on a or b, ab %lld, ba %lld\n",ab,ba);
}
}
cout<<(ans > 1e14? -1 : ans);
}
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |