Submission #506382

#TimeUsernameProblemLanguageResultExecution timeMemory
506382thomas_liOlympic Bus (JOI20_ho_t4)C++17
0 / 100
2 ms460 KiB
#include <bits/stdc++.h>
using namespace std;
const int MM = 205,MV = 5e4+5;
typedef pair<int64_t,array<int,2>> Node;
int n,m; int64_t dist[MM][MV],ans; vector<array<int,3>> adj[MM]; vector<array<int,4>> bk[MM];
array<int,4> el[MM];
int main(){
    cin.tie(0)->sync_with_stdio(0);
    cin >> n >> m; ans = 1e18;
    for(int i = 1; i <= m; i++){
        int a,b,c,d; cin >> a >> b >> c >> d;  
        el[i] = {a,b,c,d};
        adj[a].push_back({b,c,i});
        bk[b].push_back({a,c,d,i});
    }
    // took reverse edge first time on 1-n 
    {
        memset(dist,0x3f,sizeof dist);
        priority_queue<Node,vector<Node>,greater<>> q;
        for(int i = 0; i <= m; i++) dist[1][i] = el[i][3],q.push({0,{1,i}});
        while(q.size()){
            auto[d,tmp] = q.top(); q.pop();
            auto[u,i] = tmp;
            if(d > dist[u][i]) continue;
            // take regular edge
            for(auto[v,w,j]:adj[u]){
                if(j == i) continue; // flipped, original dir doesn't work
                if(dist[v][i] > dist[u][i] + w){
                    dist[v][i] = dist[u][i]+w;  
                    q.push({dist[v][i],{v,i}});
                }
            }
            // try taking back edge
            for(auto[v,w,c,j]:bk[u])if(j == i){
                if(dist[v][i] > dist[u][i]+w){
                    dist[v][i] = dist[u][i]+w;
                    q.push({dist[v][i],{v,i}});
                }   
            }
        } 
        for(int j = 0; j <= m; j++){
            if(dist[n][j] > 2e9) continue;
            q.push({dist[n][j],{n,j}});
        }
        for(int i = 1; i < n; i++){
            memset(dist[i],0x3f,sizeof dist[i]);
        }
        while(q.size()){
            auto[d,tmp] = q.top(); q.pop();
            auto[u,i] = tmp;
            if(d > dist[u][i]) continue;
            // take regular edge
            for(auto[v,w,j]:adj[u]){
                if(j == i) continue; // flipped, original dir doesn't work
                if(dist[v][i] > dist[u][i] + w){
                    dist[v][i] = dist[u][i]+w;  
                    q.push({dist[v][i],{v,i}});
                }
            }
            // try taking back edge
            for(auto[v,w,c,j]:bk[u])if(j == i){
                if(dist[v][i] > dist[u][i]+w){
                    dist[v][i] = dist[u][i]+w;
                    q.push({dist[v][i],{v,i}});
                }   
            }
        } 
        for(int i = 0; i <= m; i++) ans = min(ans,dist[1][i]);
    }
    // took reverse edge first time on n-1
    {
        memset(dist,0x3f,sizeof dist);
        priority_queue<Node,vector<Node>,greater<>> q;
        for(int i = 0; i <= m; i++) dist[n][i] = el[i][3],q.push({0,{n,i}});
        while(q.size()){
            auto[d,tmp] = q.top(); q.pop();
            auto[u,i] = tmp;
            if(d > dist[u][i]) continue;
            // take regular edge
            for(auto[v,w,j]:adj[u]){
                if(j == i) continue; // flipped, original dir doesn't work
                if(dist[v][i] > dist[u][i] + w){
                    dist[v][i] = dist[u][i]+w;  
                    q.push({dist[v][i],{v,i}});
                }
            }
            // try taking back edge
            for(auto[v,w,c,j]:bk[u])if(j == i){
                if(dist[v][i] > dist[u][i]+w){
                    dist[v][i] = dist[u][i]+w;
                    q.push({dist[v][i],{v,i}});
                }   
            }
        } 
        for(int j = 0; j <= m; j++){
            if(dist[1][j] > 2e9) continue;
            q.push({dist[1][j],{1,j}});
        }
        for(int i = 2; i <= n; i++){
            memset(dist[i],0x3f,sizeof dist[i]);
        }
        while(q.size()){
            auto[d,tmp] = q.top(); q.pop();
            auto[u,i] = tmp;
            if(d > dist[u][i]) continue;
            // take regular edge
            for(auto[v,w,j]:adj[u]){
                if(j == i) continue; // flipped, original dir doesn't work
                if(dist[v][i] > dist[u][i] + w){
                    dist[v][i] = dist[u][i]+w;  
                    q.push({dist[v][i],{v,i}});
                }
            }
            // try taking back edge
            for(auto[v,w,c,j]:bk[u])if(j == i){
                if(dist[v][i] > dist[u][i]+w){
                    dist[v][i] = dist[u][i]+w;
                    q.push({dist[v][i],{v,i}});
                }   
            }
        } 
        for(int i = 0; i <= m; i++) ans = min(ans,dist[n][i]);
    }
    cout << (ans > 2e9 ? -1 : ans) << "\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...