Submission #1268761

#TimeUsernameProblemLanguageResultExecution timeMemory
1268761YassirSalamaOlympic Bus (JOI20_ho_t4)C++20
0 / 100
950 ms12316 KiB
#pragma GCC optimize("Ofast,no-stack-protector")
#include <bits/stdc++.h>
#define  int long long
using namespace std;
#define endl "\n"
using ull=unsigned long long;
using pii=pair<int,int>;
const int dx[4] = {-1,0,1,0}, dy[4] = {0,1,0,-1};
#define OVL(x,s) for(auto y:x) cout<<y<<s; cout<<"\n";
template <typename T> istream& operator>>(istream& is, vector<T> &a) {
    copy_n(istream_iterator<T>(is), a.size(), a.begin()); return is;}
#ifdef IOI
template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
template<typename T_container, typename T = typename enable_if<!is_same<T_container, string>::value, typename T_container::value_type>::type> ostream& operator<<(ostream &os, const T_container &v) { os << '{'; string sep; for (const T &x : v) os << sep << x, sep = ", "; return os << '}'; }

void dbg_out() { cout << endl; }
template<typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cout << ' ' << H; dbg_out(T...); }
#define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__);
#else
#define dbg(...) 1337;
#endif
#define pb push_back
#define F first
#define S second
#define all(v) v.begin(),v.end()
const int maxn = 200+100;
const int mod = 1e9+7;



template < int MOD = 1000000007, typename T = int > struct ModInt {

    T val;

    ModInt(T V = 0) : val(V) { val %= MOD; }

    ModInt& operator += (const ModInt& rhs) {
        if ((val += rhs.val) >= MOD) val -= MOD;
        return *this;
    }
    ModInt& operator += (const T rhs) {
        if ((val += rhs) >= MOD) val -= MOD;
        return *this;
    }

    ModInt& operator -= (const ModInt& rhs) { 
        if ((val += MOD - rhs.val) >= MOD) val -= MOD; 
        return *this; 
    }
    ModInt& operator -= (const T rhs) { 
        if ((val += MOD - rhs) >= MOD) val -= MOD; 
        return *this; 
    }

    ModInt& operator *= (const ModInt& rhs) { val = (1ll * val * rhs.val) % MOD; return *this; }
    ModInt& operator *= (const T rhs) { val = (1ll * val * rhs) % MOD; return *this; }

    ModInt& operator /= (const ModInt& rhs) { return *this *= rhs.inverse(); }
    ModInt& operator /= (const T rhs) { return *this *= ModInt(rhs).inverse(); }

    ModInt& operator %= (const ModInt& rhs) { val %= rhs.val; return *this; }
    ModInt& operator %= (const T rhs) { val %= rhs; return *this; }

    ModInt& operator ++() { return *this += 1; }
    ModInt& operator --() { return *this -= 1; }
 
    
    ModInt operator + (const ModInt& rhs) const { ModInt res(*this); return res += rhs; }
    ModInt operator + (const T rhs) const { ModInt res(*this); return res += rhs; }

    ModInt operator % (const ModInt& rhs) const { ModInt res(*this); return res %= rhs; }
    ModInt operator % (const T rhs) const { ModInt res(*this); return res %= rhs; }

    ModInt operator - (const ModInt& rhs) const { ModInt res(*this); return res -= rhs; }
    ModInt operator - (const T rhs) const { ModInt res(*this); return res -= rhs; }

    ModInt operator * (const ModInt& rhs) const { ModInt res(*this); return res *= rhs; }
    ModInt operator * (const T rhs) const { ModInt res(*this); return res *= rhs; }

    ModInt operator / (const ModInt& rhs) const { ModInt res(*this); return res /= rhs; }
    ModInt operator / (const T rhs) const { ModInt res(*this); return res /= rhs; }

    ModInt& operator = (const ModInt& rhs) { val = rhs.val; return *this; }
    ModInt& operator = (const T rhs) { val = rhs; return *this; }

    T operator ~ () { return ~val; }
    bool operator ! () { return !val; }

    bool operator == (const ModInt& rhs) const { return val == rhs.val; }
    bool operator == (const T rhs) const { return val == rhs; }

    bool operator != (const ModInt& rhs) const { return val != rhs.val; }
    bool operator != (const T rhs) const { return val != rhs; }

    bool operator < (const ModInt& rhs) const { return val < rhs.val; }
    bool operator < (const T rhs) const { return val < rhs; }

    bool operator <= (const ModInt& rhs) const { return val <= rhs.val; }
    bool operator <= (const T rhs) const { return val <= rhs; }

    bool operator > (const ModInt& rhs) const { return val > rhs.val; }
    bool operator > (const T rhs) const { return val > rhs; }

    bool operator >= (const ModInt& rhs) const { return val >= rhs.val; }
    bool operator >= (const T rhs) const { return val >= rhs; }

    T operator () () const { return val; }

    ModInt inverse() const { return power(MOD - 2); }

    ModInt power(T n) const {
        ModInt a = *this, res = 1;
        while (n > 0) {
            if (n & 1) res *= a;
            a *= a, n >>= 1;
        }
        return res;
    }

    ModInt power(ModInt n) const {
        ModInt a = *this, res = 1;
        T e = n();
        while (e > 0) {
            if (e & 1) res *= a;
            a *= a, e >>= 1;
        }
        return res;
    }

    friend ModInt operator ^ (ModInt rhs, T n) { return rhs.power(n); }
    friend ModInt operator ^ (ModInt rhs, ModInt n) { return rhs.power(n); }

    friend std::istream& operator>>(std::istream& is, ModInt& x) noexcept { return is >> x.val; }
    friend std::ostream& operator<<(std::ostream& os, const ModInt& x) noexcept { return os << x.val; }

};
using mint = ModInt < (int)1e9+7 >;

int n,m;

set<pair<int,int>> v[maxn];
set<vector<int>> inc[maxn];

int b = 0;
vector<int> dij(int src){
    vector<int> dist(n+1,1e18);
    dist[src] = 0;
    priority_queue<pair<int,int>> q;
    q.push({0,src});
    bool visited[n+1];
    memset(visited,false,sizeof(visited));
    while(!q.empty()){
        auto [t,node] = q.top();
        q.pop();
        if(visited[node] == 1) continue;
        visited[node] = 1;
        for(auto [x,w] : v[node]){
            if(x==b) continue;
            if(visited[x]) continue;
            if(dist[x]>dist[node]+w){
                dist[x] = dist[node]+w;
                q.push({-dist[x],x});
            }
        }
   }
   return dist;
}
set<pair<int,int>> g[maxn];
vector<int> rdij(int src){
    vector<int> dist(n+1,1e18);
    dist[src] = 0;
    priority_queue<pair<int,int>> q;
    q.push({0,src});
    bool visited[n+1];
    memset(visited,false,sizeof(visited));
    while(!q.empty()){
        auto [t,node] = q.top();
        q.pop();
        if(visited[node] == 1) continue;
        visited[node] = 1;
        for(auto [x,w] : g[node]){
            if(x==b) continue;
            if(visited[x]) continue;
            if(dist[x]>dist[node]+w){
                dist[x] = dist[node]+w;
                q.push({-dist[x],x});
            }
        }
   }
   return dist;
}


signed main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>m;
    vector<vector<int>> edges;
    for(int i = 0;i<m;i++){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        edges.pb({a,b,c,d});
        v[a].insert({b,c});
        g[b].insert({a,c});
        inc[b].insert({a,c,d});
    }
    int ans = 1e18;
    b = 0;
    vector<int> bd1 = dij(1);
    vector<int> bdn = dij(n);
    vector<int> brd1 = rdij(1);
    vector<int> brdn = rdij(n);
    ans = min(ans,dij(1)[n]+dij(n)[1]);
    for(int i=1;i<=n;i++){
        b = i;
        vector<int> d1 = dij(1);
        vector<int> dn = dij(n);
        vector<int> rd1 = rdij(1);
        vector<int> rdn = rdij(n);
        //suppose we do it for incoming edges going from 1 to n
        //imagine we reverse edge a->i
        vector<pair<int,int>> a;
        set<pair<int,int>> s;        
        //dp[1][i] can't be calculated, so it's min over all other nodes
        //dp[n][i] can't be calculated too, so it's min over all other nodes
        set<vector<int>> s1,s2;
        //s1 contains d1[a]+cost
        //s2 contains dn[a]
        for(auto x : inc[i]){
            int node = x[0];
            int c = x[1];
            s1.insert({d1[node]+c,node});
            s2.insert({dn[node]+c,node});
        }
        //imagine we go from 1 to node to i
        //cost = d1[i]+c+rdn[node]+dn[1]+d
        //cost2 = d1[n]+dn[i]+c+rd1[node]+d
        //cost3 = (d1[i]+c+rdn[node])+(dn[i]+c+rd1[node])+d
        for(auto x : inc[i]){
            int node = x[0];
            int c = x[1];
            int d = x[2];
            s1.erase({d1[node]+c,node});
            s2.erase({dn[node]+c,node});
            int xx = d1[i];
            int yy = dn[i];
            if(!s1.empty()&&i!=1)
                d1[i] = (*s1.begin())[0];
            if(!s2.empty()&&i!=n)
                dn[i] = (*s2.begin())[0];
            int cost = 1e18;
            if(!s1.empty()){
            cost = d1[i]+c+rdn[node]+bdn[1]+d;
            ans = min(ans,cost);
            }
            if(!s2.empty()){
            cost = bd1[n]+dn[i]+c+rd1[node]+d;
            ans = min(ans,cost);
            }
            if(!s1.empty()&&!s2.empty()){
            cost = (d1[i]+c+rdn[node])+(dn[i]+c+rd1[node])+d;
            ans = min(ans,cost);
            }
            s1.insert({d1[node]+c,node});
            s2.insert({dn[node]+c,node});
            d1[i] = xx;
            dn[i] = yy;
        }
    }
    if(ans==1e18) ans = -1;
    cout<<ans<<endl;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...