Problem:
Downhill Race
You are participating in a ski competition held at Mt. Bandai. In this competition, each skier will ski down the slope twice and compete for the shortest total time. There are a number of flags on the slope, and a line is set up between them for the competitors to follow. Competitors follow the lines from the start point to the finish point. The lines are set up as follows.
One or more lines extend from a flag except at the finish point.
There is only one line at most that directly connects one flag to another.
The line can only be slid down in a certain direction.
You can always reach any flag from the start, and you can reach the goal from any flag.
No matter how you follow the line, you will never return to the same flag.
The athlete can decide which flag to go to next by choosing a line that extends from the flag they are currently on. The choice of line is free, so players can follow a different line to the finish point for each descent.
The night before the competition, Mr. Salt, the sports doctor, predicted the condition of the slope when you skied. According to him, the line you took on the first descent will change the snow quality due to the passage, so if you take the same line on the second descent, the time it will take may change. Salt told you how long it takes to go through each line the first time and how long it takes to go through it the second time. You must use this information to find a way to ski the line that minimizes the total time of the two descents.
Given the conditions of the slope, write a program that calculates the shortest total time for the two descents.
Input
The input is given in the following format.
N
P
s
1
e
1
t
1,1
t
1,2
s
2
e
2
t
2,1
t
2,2
:
s
P
e
P
t
P,1
t
P,2
On the first line, the number of flags
N
(2 ≤
N
≤ 1000) and the number of lines connecting the two flags
P
( 1 ≤
P
≤ 2000) are given. The flags are numbered from 1 to
N
, the starting point flag number is 1 and the goal point flag number is
N
. The following
P
lines give information about the line connecting the two flags. Each line has the source flag number
s
i
(1 ≤
s
i
<
N
), the destination flag number
e
i
(1 <
e
i
≤
N
) , time required for the first pass
t
i, 1
(1 ≤
t
i, 1
≤ 100000), the time required to pass the same line at the second time
t
i, 2
(1 ≤
t
i, 2
≤ 100000).
Output
Output the shortest value in the total time of two downhills in one line.
Sample Input 1
3 3
1 2 1 2
2 3 1 2
1 3 1 3
Sample Output 1
3
Sample Input 2
3 3
1 2 1 2
2 3 1 2
1 3 1 1
Sample Output 2
2
Sample Input 3
4 5
1 2 3 5
1 3 1 3
3 2 2 5
2 4 6 1
3 4 5 5
Sample Output 3
13

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
// #include<atcoder/all>
// using mint = atcoder::modint998244353;
using ld = long double;
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define rep(i,n) for(int i=0;i<(int)(n);++i)
template<typename T>bool chmin(T&a,T b){return b<a?(a=b,1):0;}
template<typename T>bool chmax(T&a,T b){return b>a?(a=b,1):0;}

using A3=array<int,3>;

vector<int> topological_sort(vector<vector<A3>> &G, vector<int> &indegree, int V) {
    vector<int> sorted_vertices;

    queue<int> que;
    for (int i = 0; i < V; i++) {
        if (indegree[i] == 0) {
            que.push(i);
        }
    }

    while (que.empty() == false) {
        int v = que.front();
        que.pop();

        for (int i = 0; i < G[v].size(); i++) {
            int u = G[v][i][0];
            indegree[u] -= 1;
            if (indegree[u] == 0) que.push(u);
        }
        sorted_vertices.push_back(v);
    }

    return sorted_vertices;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int N,P;
    cin>>N>>P;
    vector<vector<A3>> G(N);
    vector<int> ind(N,0);
    rep(i,P){
        int s,e,t1,t2;
        cin>>s>>e>>t1>>t2;
        s--;e--;
        G[s].push_back({e,t1,t2});
        ind[e]++;
    }

    vector<int> tp=topological_sort(G,ind,N);

    vector<int> O(N);
    rep(i,N) O[tp[i]]=i;

    vector dp(N,vector<int>(N,2e9));
    dp[0][0]=0;

    priority_queue<A3,vector<A3>,greater<A3>> pq;
    pq.push({0, 0, 0});

    while(!pq.empty()){
        auto [k,u,v]=pq.top();
        pq.pop();
        if(dp[u][v]<k) continue;
        assert(O[u]<=O[v]);
        if(u==v){
            for(A3 e: G[u]){
                for(A3 f: G[v]){
                    if(O[e[0]]>O[f[0]]) continue;
                    if(chmin(dp[e[0]][f[0]], dp[u][v]+e[1]+f[1+(e[0]==f[0])])){
                        pq.push({dp[e[0]][f[0]], e[0], f[0]});
                    }
                }
            }
        }
        else{
            for(A3 e: G[u]){
                int t1=e[0];
                int t2=v;
                if(O[t1]>O[t2]) swap(t1, t2);
                if(chmin(dp[t1][t2], dp[u][v]+e[1])){
                    pq.push({dp[t1][t2], t1, t2});
                }
            }
        }
    }
    cout<<dp[N-1][N-1]<<"\n";
    
}
accuracy: 1
time_ms: 70
memory_kb: 15292
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

constexpr ll inf = 1e18;

struct edge {
    int to;
    ll c1, c2;
};

using edges = vector<edge>;
using graph = vector<edges>;

int main() {
    int n, p;
    cin >> n >> p;
    graph g(n);
    for(int i = 0; i < p; ++i) {
        int s, e;
        ll t1, t2;
        cin >> s >> e >> t1 >> t2;
        g[s - 1].push_back(edge{e - 1, t1, t2});
    }

    vector<int> topo(n, -1);
    int idx = 0;
    function<void(int)> calc_topo = [&] (int v) {
        if(topo[v] != -1) return;
        for(auto& e : g[v]) {
            calc_topo(e.to);
        }
        topo[v] = idx++;
    };
    calc_topo(0);

    vector<vector<ll>> dist(n, vector<ll>(n, inf));
    dist[0][0] = 0;
    using state = tuple<ll, int, int>;
    priority_queue<state, vector<state>, greater<state>> que;
    que.emplace(0, 0, 0);
    while(!que.empty()) {
        ll cur_c;
        int fst_v, sec_v;
        tie(cur_c, fst_v, sec_v) = que.top();
        que.pop();
        if(fst_v == sec_v) {
            for(auto& e : g[fst_v]) {
                ll nxt_c = cur_c + e.c1 + e.c2;
                if(dist[e.to][e.to] > nxt_c) {
                    dist[e.to][e.to] = nxt_c;
                    que.emplace(nxt_c, e.to, e.to);
                }
            }

            for(auto& e1 : g[fst_v]) {
                for(auto& e2 : g[sec_v]) {
                    if(e1.to == e2.to) continue;
                    ll nxt_c = cur_c + e1.c1 + e2.c1;
                    if(dist[e1.to][e2.to] > nxt_c) {
                        dist[e1.to][e2.to] = nxt_c;
                        que.emplace(nxt_c, e1.to, e2.to);
                    }
                }
            }
        } else {
            if(topo[fst_v] > topo[sec_v]) {
                for(auto& e : g[fst_v]) {
                    ll nxt_c = cur_c + e.c1;
                    if(dist[e.to][sec_v] > nxt_c) {
                        dist[e.to][sec_v] = nxt_c;
                        que.emplace(nxt_c, e.to, sec_v);
                    }
                }
            } else {
                for(auto& e : g[sec_v]) {
                    ll nxt_c = cur_c + e.c1;
                    if(dist[fst_v][e.to] > nxt_c) {
                        dist[fst_v][e.to] = nxt_c;
                        que.emplace(nxt_c, fst_v, e.to);
                    }
                }
            }
        }
    }

    cout << dist[n - 1][n - 1] << endl;
}
accuracy: 1
time_ms: 170
memory_kb: 29284
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n,m;
	cin >> n >> m;
	vector<vector<pair<int,pair<int,int>>>> g(n,vector<pair<int,pair<int,int>>>());
	vector<int> o(n,-1);
	{
		vector<int> cou(n,0);
		for(int i = 0;i < m;i++){
			int u,v,a,b;
			cin >> u >> v >> a >> b;
			u--;v--;
			g[u].push_back({v,{a,b}});
			cou[v]++;
		}
		int now = 0;
		queue<int> q;
		q.push(0);
		while(!q.empty()){
			int it = q.front();
			q.pop();
			o[it] = now++;
			if(!g[it].empty()){
				for(pair<int,pair<int,int>> i : g[it]){
					if(--cou[i.first] == 0){
						q.push(i.first);
					}
				}
			}
		}
	}
	vector<vector<int>> d(n,vector<int>(n,false));
	{
		for(int i = 0;i < n;i++){
			d[i][i] = true;
			queue<int> q;
			q.push(i);
			while(!q.empty()){
				int it = q.front();
				q.pop();
				if(!g[it].empty()){
					for(pair<int,pair<int,int>> j : g[it]){
						if(d[i][j.first]) continue;
						d[i][j.first] = true;
						q.push(j.first);
					}
				}
			}
		}
	}
	vector<int> p(n);
	iota(p.begin(),p.end(),0);
	sort(p.begin(),p.end(),[&](int a,int b){return o[a] < o[b];});
	vector<vector<int>> ans(n,vector<int>(n,1e9));
	ans[0][0] = 0;
	for(int i = 0;i < n;i++){
		for(int j = i;j < n;j++){
			int u = p[i],v = p[j];
			for(pair<int,pair<int,int>> k : g[u]){
				if(o[k.first] > o[v]){
					ans[v][k.first] = min(ans[v][k.first],ans[u][v] + k.second.first);
				}
				for(pair<int,pair<int,int>> l : g[v]){
					if(o[l.first] > o[u]){
						ans[u][l.first] = min(ans[u][l.first],ans[u][v] + l.second.first);
					}
					if(o[k.first] > o[v] && o[l.first] > o[u]){
						if(u == v && k.first == l.first){
							ans[k.first][l.first] = min(ans[k.first][l.first],ans[u][v] + k.second.first + l.second.second);
						}else{
							if(o[k.first] < o[l.first]){
								ans[k.first][l.first] = min(ans[k.first][l.first],ans[u][v] + k.second.first + l.second.first);
							}else{
								ans[l.first][k.first] = min(ans[l.first][k.first],ans[u][v] + k.second.first + l.second.first);
							}
						}
					}
				}
			}
		}
	}
	cout << ans[n - 1][n - 1] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 11428
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

int main(){
    int n,p;
    cin>>n>>p;
    vector<vector<int>> g(n);
    vector<int> u(p),v(p),a(p),b(p);
    vector<int> cnt(n,0);
    vector<int> cmp(n,-1);
    for(int i = 0;i<p;i++){
        cin>>u[i]>>v[i]>>a[i]>>b[i];
        u[i]--;v[i]--;
        g[u[i]].push_back(v[i]);
        cnt[v[i]]++;
    }
    vector<vector<ll>> vis(n,vector<ll>(n,1e15));
    vector<vector<ll>> use(n,vector<ll>(n,0));
    deque<int> q;
    int now = 0;
    for(int i = 0;i<n;i++){
        if(cnt[i] == 0) q.push_back(i);
    }
    while(q.size()){
        int ni = q.front();
        q.pop_front();
        cmp[ni] = now++;
        for(auto&to:g[ni]) {
            cnt[to]--;
            if(cnt[to]==0) q.push_back(to);
        }
    }
    using dat = pair<ll,pair<int,int>>;
    vector<vector<pair<int,pair<ll,ll>>>> gg(n);
    for(int i = 0;i<p;i++){
        gg[u[i]].push_back(make_pair(v[i],make_pair(a[i],b[i])));
    }

    priority_queue<dat,vector<dat>,greater<dat>> que;
    que.push(make_pair(0,make_pair(0,0)));
    vis[0][0] = 0;
    while(que.size()){
        auto now = que.top();
        que.pop();
        int ni = now.second.first;
        int nj = now.second.second;
        //cout<<ni<<" "<<nj<<" "<<vis[ni][nj]<<endl;
        if(use[ni][nj]++) continue;
        if(ni==nj){
            for(int i = 0;i<gg[ni].size();i++){
                for(int j = i;j<gg[ni].size();j++){
                    if(i==j){
                        int to = gg[ni][i].first;
                        ll nxt = vis[ni][nj] + gg[ni][i].second.first + gg[ni][i].second.second;
                        if(vis[to][to]<=nxt) continue;
                        vis[to][to] = nxt;
                        que.push(make_pair(nxt,make_pair(to,to)));
                        continue;
                    }else{
                        int t1 = gg[ni][i].first;
                        int t2 = gg[ni][j].first;
                        if(cmp[t1]>cmp[t2]) swap(t1,t2);
                        ll nxt = vis[ni][nj] + gg[ni][i].second.first + gg[ni][j].second.first;
                        if(vis[t1][t2]<=nxt) continue;
                        vis[t1][t2] = nxt;
                        que.push(make_pair(nxt,make_pair(t1,t2)));
                    }
                }
            }
        }else{
            for(int i = 0;i<gg[ni].size();i++){
                int t1 = gg[ni][i].first;
                int t2 = nj;
                if(cmp[t1]>cmp[t2]) swap(t1,t2);
                ll nxt = vis[ni][nj] + gg[ni][i].second.first;
                if(vis[t1][t2]<=nxt) continue;
                vis[t1][t2] = nxt;
                que.push(make_pair(nxt,make_pair(t1,t2)));
            }
        }
    }
    cout<<vis[n-1][n-1]<<endl;

}
accuracy: 1
time_ms: 90
memory_kb: 27268
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;

template<class t>
using priority_queuer = priority_queue<t,vector<t>,greater<t>>;

int func(){
  int n;
  int p;
  cin >> n >> p;
  vector<int> waits(n,0);
  using T = tuple<int,int,int>;
  vector<vector<T>> edges(n);
  for(int i=0;i<p;++i){
    int s;
    int t;
    int t1;
    int t2;
    cin >> s >> t >> t1 >> t2;
    --s;
    --t;
    ++waits[t];
    edges[s].emplace_back(t,t1,t2);
  }
  vector<int> ranks(n,0);
  {
    queue<int> que;
    que.push(0);
    while(que.size()){
      int p = que.front();
      que.pop();
      for(auto e:edges[p]){
        ranks[get<0>(e)] = max(ranks[get<0>(e)], ranks[p] + 1);
        if(--waits[get<0>(e)] == 0){
          que.push(get<0>(e));
        }
      }
    }
  }
  vector<vector<int>> dp(n,vector<int>(n,1e9));
  priority_queuer<T> pq;
  pq.emplace(0,0,0);
  while(pq.size()){
    T tmp = pq.top();
    pq.pop();
    int cost = get<0>(tmp);
    int p1 = get<1>(tmp);
    int p2 = get<2>(tmp);
    if(p1 == p2){
      for(auto e1:edges[p1]){
        for(auto e2:edges[p1]){
          if(e1 == e2){
            int ncost = cost + get<1>(e1) + get<2>(e1);
            int np1 = get<0>(e1);
            int np2 = get<0>(e1);
            if(dp[np1][np2] > ncost){
              dp[np1][np2] = ncost;
              pq.emplace(ncost,np1,np2);
            }
          }else{
            int ncost = cost + get<1>(e1) + get<1>(e2);
            int np1 = get<0>(e1);
            int np2 = get<0>(e2);
            if(dp[np1][np2] > ncost){
              dp[np1][np2] = ncost;
              pq.emplace(ncost,np1,np2);
            }
          }
        }
      }
    }else{
      if(ranks[p1] > ranks[p2])swap(p1,p2);
      for(auto e:edges[p1]){
        int np1 = get<0>(e);
        int ncost = cost + get<1>(e);
        if(dp[np1][p2] > ncost){
          dp[np1][p2] = ncost;
          pq.emplace(ncost,np1,p2);
        }
      }
    }
  }
  return dp[n-1][n-1];
}


int main(){
  cout << func() << endl;
}
accuracy: 1
time_ms: 150
memory_kb: 20116
final_rank: 8

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <limits>
#include <queue>
#include <tuple>
using namespace std;

using ll = long long;
using state = tuple<ll, int, int>;

struct Edge {
	int to;
	ll c0;
	ll c1;
};


int idx = 0;

void calc_topo(const vector<vector<Edge>>& graph, vector<int>& topo, int v) {
	if (topo[v] != -1) {
		return;
	}
	for (const auto& e : graph[v]) {
		calc_topo(graph, topo, e.to);
	}
	topo[v] = idx++;
	return;
};

ll dijkstra(int n, const vector<vector<Edge>>& graph, const vector<int>& topo) {
	vector<vector<ll>> cost_from_s(n, vector<ll>(n, numeric_limits<ll>::max()));
	priority_queue<state, vector<state>, greater<state>> que;

	cost_from_s[0][0] = 0;
	que.emplace(0, 0, 0);
	while (!que.empty()) {
		ll c_cost = -1;
		int fv = -1;
		int sv = -1;

		tie(c_cost, fv, sv) = que.top();
		que.pop();
		if (fv == sv) {
			for (auto& e : graph[fv]) {
				ll n_cost = c_cost + e.c0 + e.c1;

				if (cost_from_s[e.to][e.to] > n_cost) {
					cost_from_s[e.to][e.to] = n_cost;
					que.emplace(n_cost, e.to, e.to);
				}
			}

			for (auto& e0 : graph[fv]) {
				for (auto& e1 : graph[sv]) {
					if (e0.to == e1.to) {
						continue;
					}

					ll n_cost = c_cost + e0.c0 + e1.c0;
					if (cost_from_s[e0.to][e1.to] > n_cost) {
						cost_from_s[e0.to][e1.to] = n_cost;
						que.emplace(n_cost, e0.to, e1.to);
					}
				}
			}
		}
		else {
			if (topo[fv] > topo[sv]) {
				for (auto& e : graph[fv]) {
					ll n_cost = c_cost + e.c0;
					if (cost_from_s[e.to][sv] > n_cost) {
						cost_from_s[e.to][sv] = n_cost;
						que.emplace(n_cost, e.to, sv);
					}
				}
			}
			else {
				for (auto& e : graph[sv]) {
					ll n_cost = c_cost + e.c0;
					if (cost_from_s[fv][e.to] > n_cost) {
						cost_from_s[fv][e.to] = n_cost;
						que.emplace(n_cost, fv, e.to);
					}
				}
			}
		}
	}
	return cost_from_s[n - 1][n - 1];
}

int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	int n = -1;
	int p = -1;

	cin >> n >> p;

	vector<vector<Edge>> graph(n);
	for (int i = 0; i < p; ++i) {
		int s = -1;
		int e = -1;
		ll t0 = -1;
		ll t1 = -1;

		cin >> s >> e >> t0 >> t1;
		graph[s - 1].push_back(Edge{ e - 1, t0, t1 });
	}

	vector<int> topo(n, -1);

	idx = 0;
	calc_topo(graph, topo, 0);
	cout << dijkstra(n, graph, topo) << endl;
	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 28720
final_rank: 9

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <limits>
#include <queue>
#include <tuple>
using namespace std;

using ll = long long;

struct Edge {
    int to;
    ll c0;
    ll c1;
};


int idx = 0;


void calc_topo(const vector<vector<Edge>>& g, vector<int>& topo, int v) {
	if (topo[v] != -1) return;
	for (const auto& e : g[v]) {
		calc_topo(g, topo, e.to);
	}
	topo[v] = idx++;
};

ll dijkstra(int n, const vector<vector<Edge>>& g, const vector<int>& topo){
    vector<vector<ll>> dist(n, vector<ll>(n, numeric_limits<ll>::max()));
    dist[0][0] = 0;
    using state = tuple<ll, int, int>;
    priority_queue<state, vector<state>, greater<state>> que;
    que.emplace(0, 0, 0);
    while(!que.empty()) {
        ll cur_c;
        int fst_v, sec_v;
        tie(cur_c, fst_v, sec_v) = que.top();
        que.pop();
        if(fst_v == sec_v) {
            for(auto& e : g[fst_v]) {
                ll nxt_c = cur_c + e.c0 + e.c1;
                if(dist[e.to][e.to] > nxt_c) {
                    dist[e.to][e.to] = nxt_c;
                    que.emplace(nxt_c, e.to, e.to);
                }
            }

            for(auto& e1 : g[fst_v]) {
                for(auto& e2 : g[sec_v]) {
                    if(e1.to == e2.to) continue;
                    ll nxt_c = cur_c + e1.c0 + e2.c0;
                    if(dist[e1.to][e2.to] > nxt_c) {
                        dist[e1.to][e2.to] = nxt_c;
                        que.emplace(nxt_c, e1.to, e2.to);
                    }
                }
            }
        } else {
            if(topo[fst_v] > topo[sec_v]) {
                for(auto& e : g[fst_v]) {
                    ll nxt_c = cur_c + e.c0;
                    if(dist[e.to][sec_v] > nxt_c) {
                        dist[e.to][sec_v] = nxt_c;
                        que.emplace(nxt_c, e.to, sec_v);
                    }
                }
            } else {
                for(auto& e : g[sec_v]) {
                    ll nxt_c = cur_c + e.c0;
                    if(dist[fst_v][e.to] > nxt_c) {
                        dist[fst_v][e.to] = nxt_c;
                        que.emplace(nxt_c, fst_v, e.to);
                    }
                }
            }
        }
    }
    return dist[n - 1][n - 1];
}

int main() {
#if READ_FROM_FILE
    ifstream ifs("test0.txt");
    cin.rdbuf(ifs.rdbuf());
#endif
    int n, p;
    cin >> n >> p;
    vector<vector<Edge>> g(n);
    for (int i = 0; i < p; ++i) {
        int s, e;
        ll t0, t1;
        cin >> s >> e >> t0 >> t1;
        g[s - 1].push_back(Edge{ e - 1, t0, t1 });
    }

    vector<int> topo(n, -1);
    int idx = 0;
    calc_topo(g, topo, 0);
    cout << dijkstra(n, g, topo) << endl;
    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 29184
final_rank: 10

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 0324.cc: Downhill Race
 */

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<utility>
 
using namespace std;

/* constant */

const int MAX_N = 1000;
const int MAX_M = 2000;
const long long LINF = 1LL << 62;

/* typedef */

typedef long long ll;
typedef queue<int> qi;
typedef pair<int,int> pii;
typedef vector<pii> vpii;

struct Stat {
  ll d;
  int i, j;
  Stat() {}
  Stat(ll _d, int _i, int _j): d(_d), i(_i), j(_j) {}
  bool operator<(const Stat &s) const { return d > s.d; }
};

/* global variables */

vpii nbrs[MAX_N];
int ts0[MAX_M], ts1[MAX_M];
int pns[MAX_N], ods[MAX_N];
ll ds[MAX_N][MAX_N];

/* subroutines */

/* main */

int main() {
  //freopen("input.txt", "r", stdin);
  //freopen("output.txt", "w", stdout);

  int n, m;
  scanf("%d%d", &n, &m);

  for (int i = 0; i < m; i++) {
    int u, v;
    scanf("%d%d%d%d", &u, &v, ts0 + i, ts1 + i);
    u--, v--;
    nbrs[u].push_back(pii(v, i));
    pns[v]++;
  }

  qi q;
  q.push(0);

  for (int k = 0; ! q.empty();) {
    int u = q.front(); q.pop();
    ods[u] = k++;
    for (auto ve: nbrs[u]) {
      int v = ve.first;
      if (--pns[v] == 0) q.push(v);
    }
  }
  //for (int i = 0; i < n; i++) printf("%d ", ods[i]); putchar('\n');

  for (int i = 0; i < n; i++) fill(ds[i], ds[i] + n, LINF);
  ds[0][0] = 0;

  priority_queue<Stat> pq;
  pq.push(Stat(0, 0, 0));

  while (! pq.empty()) {
    Stat u = pq.top(); pq.pop();
    if (ds[u.i][u.j] != u.d) continue;
    if (u.i == n - 1 && u.j == n - 1) break;

    if (u.i == u.j) {
      for (auto ve: nbrs[u.i]) {
	int v = ve.first, ei = ve.second;
	ll vd = u.d + ts0[ei] + ts1[ei];
	if (ds[v][v] > vd) {
	  ds[v][v] = vd;
	  pq.push(Stat(vd, v, v));
	}
      }

      for (auto vei: nbrs[u.i]) {
	int vi = vei.first, ei = vei.second;
	for (auto vej: nbrs[u.j]) {
	  int vj = vej.first, ej = vej.second;
	  if (vi != vj) {
	    int tvi = vi, tvj = vj;
	    if (ods[tvi] > ods[tvj]) swap(tvi, tvj);
	    ll vd = u.d + ts0[ei] + ts0[ej];
	    if (ds[tvi][tvj] > vd) {
	      ds[tvi][tvj] = vd;
	      pq.push(Stat(vd, tvi, tvj));
	    }
	  }
	}
      }
    }
    else {
      for (auto ve: nbrs[u.i]) {
	int vi = ve.first, vj = u.j, ei = ve.second;
	if (ods[vi] > ods[vj]) swap(vi, vj);
	ll vd = u.d + ts0[ei];
	if (ds[vi][vj] > vd) {
	  ds[vi][vj] = vd;
	  pq.push(Stat(vd, vi, vj));
	}
      }
    }
  }

  printf("%lld\n", ds[n - 1][n - 1]);
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 19648
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<P,ll>;
using PP = pair<P, P>;
constexpr int INF = 1 << 28;
constexpr ll MOD = ll(1e9)+7;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-9;


struct edge{
    int to, cap, cost, rev;
};

using Graph = vector<vector<edge> >;

Graph G1, G2;
vector<int> dist;

void add_edge(Graph& g, int from, int to, int cap, int cost){
    g[from].push_back((edge){to, cap, cost, int(g[to].size())});
    g[to].push_back((edge){from, 0, -cost, int(g[from].size())-1});
}

// 最小費用流
int min_cost_flow(int s, int t, int f, Graph G){
    vector<int> h, prevv, preve;
    h.resize(G.size());
    dist.resize(G.size());
    prevv.resize(G.size());
    preve.resize(G.size());
    int res = 0;
    fill(h.begin(), h.end(), 0);
    while(f > 0){
        priority_queue<P, vector<P>, greater<P> > que;
        fill(dist.begin(), dist.end(), INF);
        dist[s] = 0;
        que.push({0,s});
        while(!que.empty()){
            P p = que.top();
            que.pop();
            int v = p.second;
            if(dist[v] < p.first) continue;
            for(int i=0;i<int(G[v].size());i++){
                auto &e = G[v][i];
                if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]){
                    dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    que.push({dist[e.to], e.to});
                }
            }
        }
        if(dist[t] == INF){
            return INF;
        }
        for(int v=0; v<G.size(); v++) h[v] += dist[v];
        int d = f;
        for(int v=t; v!=s; v=prevv[v]){
            d = min(d, G[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d*h[t];
        for(int v=t; v!=s; v=prevv[v]){
            auto &e = G[prevv[v]][preve[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}

void dijkstra(int s){
    priority_queue<P, vector<P>, greater<P> > que;
    fill(dist.begin(), dist.end(), INF);
    dist[s] = 0;
    que.push({0,s});
    while(!que.empty()){
        P p = que.top();
        que.pop();
        int v = p.second;
        if(dist[v] < p.first) continue;
        for(int i=0;i<int(G2[v].size());i++){
            auto &e = G2[v][i];
            if(e.cost < 0) continue;
            if(dist[e.to] > dist[v] + e.cost){
                dist[e.to] = dist[v] + e.cost;
                que.push({dist[e.to], e.to});
            }
        }
    }
}

int solve(){
    int N, M;
    cin >> N >> M;
    G1.resize(N);
    G2.resize(N);
    for(int i=0;i<M;i++){
        int s, e, t1, t2;
        cin >> s >> e >> t1 >> t2;
        s--; e--;
        add_edge(G1, s, e, 1, t1);
        add_edge(G2, s, e, 1, t1+t2);
    }
    vector<int> x(N), y(N);
    for(int i=0;i<N;i++){
        x[i] = min_cost_flow(0,i,2, G1);
        y[i] = min_cost_flow(i,N-1,2, G1);
    }
    int ans = INF;
    for(int i=0;i<N;i++){
        dijkstra(i);
        for(int j=0;j<N;j++){
            ans = min(ans, x[i]+dist[j]+y[j]);
        }
    }
    cout << ans << endl;
    return 0;
}

int main(){

    solve();
    // while(solve()==0);
    // int t; cin >> t; for(;t>0;t--) solve();
    return 0;
}
accuracy: 0.625
time_ms: 330
memory_kb: 3464
final_rank: 20

code_snippet: #include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 2012345678;
int main() {
	int N, P;
	cin >> N >> P;
	vector<vector<int> > G(N);
	vector<int> deg(N);
	vector<int> A(P), B(P), C1(P), C2(P);
	for (int i = 0; i < P; ++i) {
		cin >> A[i] >> B[i] >> C1[i] >> C2[i]; --A[i], --B[i];
		G[A[i]].push_back(B[i]);
		++deg[B[i]];
	}
	queue<int> que;
	for (int i = 0; i < N; ++i) {
		if (deg[i] == 0) que.push(i);
	}
	vector<int> ord(N, -1);
	int cur = 0;
	while (!que.empty()) {
		int u = que.front(); que.pop();
		ord[u] = cur++;
		for (int i : G[u]) {
			--deg[i];
			if (deg[i] == 0) que.push(i);
		}
	}
	vector<int> perm(P);
	for (int i = 0; i < P; ++i) perm[i] = i;
	sort(perm.begin(), perm.end(), [&](int i, int j) {
		return B[i] != B[j] ? ord[B[i]] < ord[B[j]] : ord[A[i]] < ord[A[j]];
	});
	vector<int> ip(N);
	for (int i = 0; i < N; ++i) ip[ord[i]] = i;
	vector<int> rip = ip;
	reverse(rip.begin(), rip.end());
	vector<vector<int> > dp(N, vector<int>(N, inf));
	dp[0][0] = 0;
	for (int i : perm) {
		for (int j : rip) {
			dp[B[i]][j] = min(dp[B[i]][j], dp[A[i]][j] + C1[i]);
			dp[j][B[i]] = min(dp[j][B[i]], dp[j][A[i]] + C1[i]);
		}
		dp[B[i]][B[i]] = min(dp[B[i]][B[i]], dp[A[i]][A[i]] + C1[i] + C2[i]);
	}
	cout << dp[N - 1][N - 1] << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 6844
final_rank: 2

code_snippet: #include<algorithm>
#include<cassert>
#include<climits>
#include<cmath>
#include<cstring>
#include<deque>
#include<functional>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<vector>

using namespace std;

using lint = long long;
using P = pair<int, int>;
using LLP = pair<long long, long long>;

#define REP(i, x, n) for(int i = (x), i##_len = int(n) ; i < i##_len ; ++i)
#define rep(i, n) for(int i = 0, i##_len = int(n) ; i < i##_len ; ++i)
#define reps(i, n) for(int i = 1, i##_len = int(n) ; i <= i##_len ; ++i)
#define rrep(i, n) for(int i = int(n) - 1 ; i >= 0 ; --i)
#define rreps(i, n) for(int i = int(n) ; i > 0 ; --i)
#define SORT(x) sort((x).begin(), (x).end())
#define SORT_INV(x) sort((x).rbegin(), (x).rend())
#define TWINS(x) cout << ((x) ? "Yay!" : ":(") << endl

constexpr int IINF = (1 << 30) - 1;
constexpr long long LLINF = 1LL << 61;
constexpr double EPS = 1e-8;

const int dx4[] = {1, 0, -1, 0}, dy4[] = {0, 1, 0, -1};
const int dx8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dy8[] = {0, -1, -1, -1, 0, 1, 1, 1};

struct edge{
    int to;
    lint cost1, cost2;
};

struct node{
    int f, s;
    lint cost;

    bool operator<(const node& rhs) const {
        return cost > rhs.cost;
    }
};

template<typename T>
bool chmax(T& a, T b, bool equal = false){
    if(a < b || equal && a == b){
        a = b;
        return true;
    }
    return false;
}

template<typename T>
bool chmin(T& a, T b, bool equal = false){
    if(b < a || equal && a == b){
        a = b;
        return true;
    }
    return false;
}

bool topological_sort(const vector< vector<edge> >& g, vector<int>& res){
    const int v = (int)g.size();
    res.clear();

    vector<int> deg(v, 0);
    for(int i = 0 ; i < v ; ++i){
        for(auto e : g[i]){
            ++deg[e.to];
        }
    }

    vector<int> st;
    for(int i = 0 ; i < v ; ++i){
        if(deg[i] == 0){
            st.emplace_back(i);
        }
    }

    while(!st.empty()){
        int k = st.back();
        st.pop_back();
        res.emplace_back(k);
        for(auto e : g[k]){
            --deg[e.to];
            if(deg[e.to] == 0){
                st.emplace_back(e.to);
            }
        }
    }

    return (int)res.size() == v;
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    int n, p;
    cin >> n >> p;

    vector< vector<edge> > g(n);
    rep(i, p){
        int s, e;
        lint t1, t2;
        cin >> s >> e >> t1 >> t2;
        g[--s].push_back({--e, t1, t2});
    }

    vector<int> v;
    assert(topological_sort(g, v));

    vector<int> rev(n);
    rep(i, n){
        rev[v[i]] = i;
    }

    vector< vector<lint> > cost(n, vector<lint>(n, LLINF));
    cost[0][0] = 0;
    priority_queue<node> que;
    que.push({0, 0, 0LL});

    while(!que.empty()){
        node now = que.top();
        que.pop();
        if(cost[now.f][now.s] < now.cost){
            continue;
        }
        if(now.f == now.s){
            for(auto e1 : g[now.f]){
                for(auto e2 : g[now.s]){
                    if(e1.to == e2.to){
                        if(chmin(cost[e1.to][e1.to], now.cost + e1.cost1 + e1.cost2)){
                            que.push({e1.to, e1.to, now.cost + e1.cost1 + e1.cost2});
                        }
                    }else{
                        if(chmin(cost[e1.to][e2.to], now.cost + e1.cost1 + e2.cost1)){
                            que.push({e1.to, e2.to, now.cost + e1.cost1 + e2.cost1});
                        }
                    }
                }
            }
        }else if(rev[now.f] < rev[now.s]){
            for(auto e : g[now.f]){
                if(chmin(cost[e.to][now.s], now.cost + e.cost1)){
                    que.push({e.to, now.s, now.cost + e.cost1});
                }
            }
        }else{
            for(auto e : g[now.s]){
                if(chmin(cost[now.f][e.to], now.cost + e.cost1)){
                    que.push({now.f, e.to, now.cost + e.cost1});
                }
            }
        }
    }

    cout << cost[n - 1][n - 1] << endl;

    return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 27172
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = long long;
using std::cout;
using std::endl;
using std::cin;

template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

int main() {
	int n, m; scanf("%d%d", &n, &m);
	std::vector<std::vector<std::pair<int, int>>> g(n);
	std::vector<int> x(m), y(m), h(n, 0);
	for(int i = 0; i < m; i++) {
		int a, b; scanf("%d%d%d%d", &a, &b, &x[i], &y[i]);
		
		g[a - 1].push_back({b - 1, i});
		h[b - 1]++;
	}
	
	std::vector<int> latte, malta(n);
	std::queue<int> qu; qu.push(0);
	while(!qu.empty()) {
		auto p = qu.front(); qu.pop();
		
		latte.push_back(p);
		for(auto e: g[p]) if(!(--h[e.first])) qu.push(e.first);
	}
	for(int i = 0; i < n; i++) malta[latte[i]] = i;
	
	auto dp = make_v<int>(n, n, 2);
	for(auto& w: dp) for(auto& v: w) for(auto& z: v) z = 1 << 30; dp[0][0][0] = 0;
	for(int i = 0; i < n; i++) {
		for(int j = 0; j < i; j++) {
			for(auto e: g[latte[j]]) {
				int to = malta[e.first], X = x[e.second], Y = y[e.second];
				
				if(i < to) {
					dp[to][i][0] = std::min({dp[to][i][0],
											 dp[i][j][0] + X,
											 dp[i][j][1] + X});
				} else if(to < i) {
					dp[i][to][0] = std::min({dp[i][to][0],
											 dp[i][j][0] + X,
											 dp[i][j][1] + X});
				} else {
					dp[to][to][0] = std::min({dp[to][to][0],
											  dp[i][j][0] + X,
											  dp[i][j][1] + Y});
				}
			}
			
		}
		int j = i;
		for(auto e: g[latte[j]]) {
			int to = malta[e.first], X = x[e.second], Y = y[e.second];
			
			dp[to][i][1] = std::min(dp[to][i][1], dp[i][j][0] + X);
		}
	}
	printf("%d\n", std::min(dp[n - 1][n - 1][0], dp[n - 1][n - 1][1]));
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 58148
final_rank: 12

code_snippet: //#define NDEBUG
#include <cstddef>
#include <cstdint>
#include <vector>

namespace n91 {

using i8 = std::int_fast8_t;
using i32 = std::int_fast32_t;
using i64 = std::int_fast64_t;
using u8 = std::uint_fast8_t;
using u32 = std::uint_fast32_t;
using u64 = std::uint_fast64_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;

constexpr usize operator"" _z(unsigned long long x) noexcept {
  return static_cast<usize>(x);
}

class rep {
  const usize f, l;

public:
  class itr {
    friend rep;
    usize i;
    constexpr itr(const usize x) noexcept : i(x) {}

  public:
    void operator++() noexcept { ++i; }
    constexpr usize operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
  };
  constexpr rep(const usize first, const usize last) noexcept
      : f(first), l(last) {}
  constexpr itr begin() const noexcept { return itr(f); }
  constexpr itr end() const noexcept { return itr(l); }
};
class revrep {
  const usize f, l;

public:
  class itr {
    friend revrep;
    usize i;
    constexpr itr(usize x) noexcept : i(x) {}

  public:
    void operator++() noexcept { --i; }
    constexpr usize operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
  };
  constexpr revrep(usize first, usize last) noexcept : f(--first), l(--last) {}
  constexpr itr begin() const noexcept { return itr(l); }
  constexpr itr end() const noexcept { return itr(f); }
};
template <class T> using vec_alias = std::vector<T>;
template <class T> auto md_vec(const usize n, const T &value) {
  return std::vector<T>(n, value);
}
template <class... Args> auto md_vec(const usize n, Args... args) {
  return std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
}
template <class T> constexpr T difference(const T &a, const T &b) {
  return a < b ? b - a : a - b;
}

} // namespace n91

#include <vector>

namespace nimi {
struct base_edge {
  std::size_t from;
  std::size_t to;
  base_edge(std::size_t from, std::size_t to) : from(from), to(to) {}
};

template <class T> struct edge : public base_edge {
  T val;
  edge(std::size_t from, std::size_t to, T v) : base_edge(from, to), val(v) {}
};

template <> struct edge<void> : public base_edge {
  edge(std::size_t from, std::size_t to) : base_edge(from, to) {}
};
template <class C> struct maxflow_edge : public base_edge {
  C cap;
  std::size_t rev;
  maxflow_edge(std::size_t from, std::size_t to, C cap, std::size_t rev)
      : base_edge(from, to), cap(cap), rev(rev) {}
};

template <class T>
struct directed_graph : public std::vector<std::vector<edge<T>>> {
  directed_graph(std::size_t n) : std::vector<std::vector<edge<T>>>(n) {}
  void add_edge(const edge<T> &e) { this->at(e.from).push_back(e); }
};

template <class T>
struct undirected_graph : public std::vector<std::vector<edge<T>>> {
  undirected_graph(std::size_t n) : std::vector<std::vector<edge<T>>>(n) {}
  void add_edge(const edge<T> &e) {
    this->at(e.from).push_back(e);
    edge<T> re = e;
    std::swap(re.from, re.to);
    this->at(e.to).push_back(re);
  }
};

template <class C>
struct maxflow_graph : public std::vector<std::vector<maxflow_edge<C>>> {
  maxflow_graph(std::size_t n) : std::vector<std::vector<maxflow_edge<C>>>(n) {}
  void add_edge(std::size_t from, std::size_t to, C cap,
                std::size_t rev_cap = 0) {
    this->at(from).push_back(
        maxflow_edge<C>(from, to, cap, this->at(to).size()));
    this->at(to).push_back(
        maxflow_edge<C>(to, from, rev_cap, this->at(from).size() - 1));
  }
};
} // namespace nimi

#include <limits>
#include <queue>
#include <vector>

namespace nimi {
template <class T>
std::vector<T> dijkstra(const nimi::directed_graph<T> &g, std::size_t s) {
  const T INF = std::numeric_limits<T>::max();
  const T ZERO = T();
  const std::size_t n = g.size();

  struct node {
    T dist;
    std::size_t vertex;
    node(T d, std::size_t v) : dist(d), vertex(v) {}
    bool operator<(const node &n) const { return n.dist < dist; }
  };

  std::vector<T> dist(n, INF);
  std::priority_queue<node> que;

  dist[s] = ZERO;
  que.emplace(dist[s], s);

  while (!que.empty()) {
    node p = que.top();
    T d = p.dist;
    std::size_t v = p.vertex;
    que.pop();
    if (dist[v] < d)
      continue;
    for (const auto &e : g[v]) {
      if (dist[v] + e.val < dist[e.to]) {
        dist[e.to] = dist[v] + e.val;
        que.emplace(dist[e.to], e.to);
      }
    }
  }
  return std::move(dist);
}
} // namespace nimi

#include <algorithm>
#include <iostream>
#include <utility>

namespace n91 {

void main_() {
  usize n, p;
  std::cin >> n >> p;
  nimi::directed_graph<u32> g(n * (n + 1_z) / 2_z);
  const auto get = [](const usize i, const usize j) {
    if (i >= j) {
      return i * (i + 1_z) / 2_z + j;
    } else {
      return j * (j + 1_z) / 2_z + i;
    }
  };
  {
    struct edge {
      usize to;
      u32 c0, c1;
    };
    std::vector<std::vector<edge>> h(n);
    std::vector<usize> deg(n);
    for (const auto i : rep(0_z, p)) {
      usize s, e;
      u32 t1, t2;
      std::cin >> s >> e >> t1 >> t2;
      --s;
      --e;
      h[s].push_back({e, t1, t2});
      ++deg[e];
    }

    // topological sort
    std::vector<usize> index;
    std::vector<usize> stack;
    stack.push_back(0_z);
    while (!stack.empty()) {
      const usize v = stack.back();
      stack.pop_back();
      index.push_back(v);
      for (const auto &e : h[v]) {
        --deg[e.to];
        if (deg[e.to] == 0_z) {
          stack.push_back(e.to);
        }
      }
    }

    for (auto i = index.cbegin(); i != index.cend(); ++i) {
      for (auto j = index.cbegin(); j != i; ++j) {
        for (const auto &e : h[*j]) {
          g.add_edge({get(*i, *j), get(*i, e.to), e.c0});
        }
      }
      for (auto j = h[*i].cbegin(); j != h[*i].cend(); ++j) {
        for (auto k = h[*i].cbegin(); k != j; ++k) {
          g.add_edge({get(*i, *i), get(j->to, k->to), j->c0 + k->c0});
        }
        g.add_edge({get(*i, *i), get(j->to, j->to), j->c0 + j->c1});
      }
    }
  }
  std::cout << nimi::dijkstra(g, get(0_z, 0_z))[get(n - 1_z, n - 1_z)]
            << std::endl;
}

} // namespace n91

int main() {
  n91::main_();
  return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 85808
final_rank: 19

code_snippet: # include <iostream>
# include <algorithm>
#include <array>
# include <cassert>
#include <cctype>
#include <climits>
#include <numeric>
# include <vector>
# include <string>
# include <set>
# include <map>
# include <cmath>
# include <iomanip>
# include <functional>
# include <tuple>
# include <utility>
# include <stack>
# include <queue>
# include <list>
# include <bitset>
# include <complex>
# include <chrono>
# include <random>
# include <limits.h>
# include <unordered_map>
# include <unordered_set>
# include <deque>
# include <cstdio>
# include <cstring>
#include <stdio.h>
#include<time.h>
#include <stdlib.h>
#include <cstdint>
#include <cfenv>
#include<fstream>
//#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
long long MOD = 1000000000 + 7;
constexpr long long INF = numeric_limits<LL>::max();
const double PI = acos(-1);
#define fir first
#define sec second
#define thi third
#define debug(x) cerr<<#x<<": "<<x<<'\n'
typedef pair<LL, LL> Pll;
typedef pair<LL, pair<LL, LL>> Ppll;
typedef pair<LL, pair<LL, bitset<100001>>> Pbll;
typedef pair<LL, pair<LL, vector<LL>>> Pvll;
typedef pair<LL, LL> Vec2;
struct Tll { LL first, second, third; };
struct Fll { LL first, second, third, fourd; };
typedef pair<LL, Tll> Ptll;
#define rep(i,rept) for(LL i=0;i<rept;i++)
#define Mfor(i,mf) for(LL i=mf-1;i>=0;i--)
LL h, w, n, m, k, t, s, p, q, last, cnt, sum, ans, d[2000][2000], a[60000], b[60000];
string str, ss;
bool f[2000][2000];
char c;
int di[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };
struct Edge { LL to, cost1, cost2; };
vector<Edge>vec[200000];
vector<LL>v;
map<LL, LL>ma;
multiset<LL>st;

void YN(bool f) {
	if (f)
		cout << "YES" << endl;
	else
		cout << "NO" << endl;
}
void yn(bool f) {
	if (f)
		cout << "Yes" << endl;
	else
		cout << "No" << endl;
}
vector<int> tsort(vector<vector<Edge>>g) {
	int n = g.size();
	enum { YET, VISITED, DONE };
	vector<int> res, flg(g.size(), YET);
	static const function<bool(int)> dfs = [&](int v) {
		flg[v] = VISITED;
		for (auto &e : g[v]) {
			int w = e.to;
			if (flg[w] != DONE && (flg[w] == VISITED || !dfs(w))) return false;
		}
		flg[v] = DONE;
		res.push_back(v);
		return true;
	};
	for (int i = 0; i < n; ++i)
		if (flg[i] == YET && !dfs(i)) return{};
	reverse(res.begin(), res.end());
	return res;
}

void dijk(vector<int>ts, vector<vector<Edge>>g) {
	rep(i,2000)rep(j,2000)
		d[i][j] = INF;
	d[0][0] = 0;
	priority_queue<Ppll, vector<Ppll>, greater<Ppll>> pq;
	pq.push(Ppll(d[0][0], Pll(0, 0))); // (cost,頂点番号) 
	while (!pq.empty()) {
		Ppll pp;
		pp = pq.top();
		LL cos = pp.first, vv[2] = { pp.second.first, pp.second.second }, x = 0;
		pq.pop();
		if (d[vv[0]][vv[1]] < pp.first)continue;
		if (vv[0]== vv[1]) {
			for (int i = 0; i < g[vv[0]].size(); i++) {
				if (d[vv[0]][vv[1]] + g[vv[0]][i].cost1 + g[vv[0]][i].cost2 < d[g[vv[0]][i].to][g[vv[0]][i].to]) {
					d[g[vv[0]][i].to][g[vv[0]][i].to] =
						d[vv[0]][vv[1]] + g[vv[0]][i].cost1 + g[vv[0]][i].cost2;
					pq.push(Ppll(d[g[vv[0]][i].to][g[vv[1]][i].to], Pll(g[vv[0]][i].to, g[vv[1]][i].to)));
				}
			}

			for (int i = 0; i < g[vv[0]].size(); i++) {
				for (int j = 0; j < g[vv[1]].size(); j++) {
					if (g[vv[0]][i].to == g[vv[1]][j].to)continue;

					if (d[vv[0]][vv[1]] + g[vv[0]][i].cost1 + g[vv[1]][j].cost1 < d[g[vv[0]][i].to][g[vv[1]][j].to]) {
						d[g[vv[0]][i].to][g[vv[1]][j].to] = d[vv[0]][vv[1]] + g[vv[0]][i].cost1 + g[vv[1]][j].cost1;
						pq.push(Ppll(d[g[vv[0]][i].to][g[vv[1]][j].to], Pll(g[vv[0]][i].to, g[vv[1]][j].to)));
					}
				}
			}

		}
		else {
			if (ts[vv[1]] < ts[vv[0]])x = 1;

			LL vt[2] = { vv[0],vv[1] };
			for (int i = 0; i < g[vv[x]].size(); i++) {
				vt[x] = g[vv[x]][i].to;
				if (d[vt[0]][vt[1]] > g[vv[x]][i].cost1 + d[vv[0]][vv[1]]) {
					d[vt[0]][vt[1]] = g[vv[x]][i].cost1 + d[vv[0]][vv[1]];
					pq.push(Ppll(d[vt[0]][vt[1]], Pll(vt[0], vt[1])));
				}
			}

		}
	}
}



int main() {
	cin >> n >> m;
	vector<vector<Edge>>g(n);
	rep(i, m) {
		LL x, y, z, w;
		cin >> x >> y >> z >> w;
		x--, y--;
		g[x].push_back(Edge{ y,z,w });
	}
	dijk(tsort(g),g);
	cout << (d[n - 1][n - 1]==INF?0:d[n-1][n-1]) << endl;
	return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 63588
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define INF_LL (int64)1e18
#define INF (int32)1e9
#define REP(i, n) for(int64 i = 0;i < (n);i++)
#define FOR(i, a, b) for(int64 i = (a);i < (b);i++)
#define all(x) x.begin(),x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using uint32 = uint_fast32_t;
using int64 = int_fast64_t;
using uint64 = uint_fast64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

const double eps = 1e-10;

template<typename A, typename B>inline void chmin(A &a, B b){if(a > b) a = b;}
template<typename A, typename B>inline void chmax(A &a, B b){if(a < b) a = b;}

using T = tuple<int32, int32, int32>;

int32 N, P;
vector<T> G[1010];
vector<int32> a, inv;
vector<bool> visited;

void visit(int32 v){
	if(!visited[v]){
		visited[v] = 1;
		REP(i, G[v].size()){
			visit(get<2>(G[v][i]));
		}
		a.push_back(v);
	}
}

int64 dp[1010][1010][2] = {};

int main(void){
	cin >> N >> P;
	visited = vector<bool>(N);

	REP(i, 1010) REP(j, 1010) REP(k, 2) dp[i][j][k] = INF_LL;

	REP(i, P){
		int32 u, v, t1, t2;
		cin >> u >> v >> t1 >> t2; u--; v--;
		G[u].push_back(T(t1, t2, v));
	}
	REP(i, N) visit(i);
	reverse(all(a));
	inv.resize(N);
	REP(i, N){
		inv[a[i]] = i;
	}
	dp[0][0][0] = 0;

	REP(i, N){
		REP(j, N){
			REP(l, 2){
				if(i <= j){
					REP(k, G[a[i]].size()){
						int32 c1, c2, v;
						tie(c1, c2, v) = G[a[i]][k];
						v = inv[v];
						if(v == j){
							if(l == 1)
								chmin(dp[v][j][0], dp[i][j][l]+c2);
							else
								chmin(dp[v][j][0], dp[i][j][l]+c1);
						}else{
							if(j < v && i == j)
								chmin(dp[v][j][1], dp[i][j][l]+c1);
							else
								chmin(dp[v][j][0], dp[i][j][l]+c1);
						}
					}
				}
				if(j <= i){
					REP(k, G[a[j]].size()){
						int32 c1, c2, v;
						tie(c1, c2, v) = G[a[j]][k];
						v = inv[v];
						if(v == i){
							if(l == 1)
								chmin(dp[i][v][0], dp[i][j][l]+c2);
							else
								chmin(dp[i][v][0], dp[i][j][l]+c1);
						}else{
							if(i < v && i == j)
								chmin(dp[i][v][1], dp[i][j][l]+c1);
							else
								chmin(dp[i][v][0], dp[i][j][l]+c1);
						}
					}
				}
			}
		}
	}
	cout << min(dp[N-1][N-1][0], dp[N-1][N-1][1]) << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 19172
final_rank: 4

code_snippet: #include <stdio.h>
#include <vector>
#include <utility>
using namespace std;
typedef pair<int,int> pi;
#define F first
#define S second
#define PB push_back
const int N=1e3+10;
const int INF=1e9+10;
int n,dp[N][N],pos[N],top;
vector<pair<int,pi>>graph[N];
void swap(int &a,int &b){
    int temp=a;
    a=b;
    b=temp;
    return ;
}
int f(int a,int b){
    if(pos[a]==n&&pos[b]==n)return 0;
    if(pos[a]>pos[b])swap(a,b);
    if(dp[a][b]>=0)return dp[a][b];
    int ans=INF;
    if(a==b)for(pair<int,pi> i:graph[a])for(pair<int,pi> j:graph[a]){
        if(i==j)ans=min(ans,i.S.F+i.S.S+f(i.F,i.F));
        else ans=min(ans,i.S.F+j.S.F+f(i.F,j.F));
    }
    else for(pair<int,pi> i:graph[a])ans=min(ans,i.S.F+f(i.F,b));
    return dp[a][b]=ans;
}
void dfs(int now){
    for(pair<int,pi> i:graph[now])if(pos[i.F]<0)dfs(i.F);
    pos[now]=top--;
    return ;
}
int main(){
    int m,l,r,a,b;
    scanf("%d%d",&n,&m);
    top=n;
    for(int i=1;i<=n;i++)pos[i]=-1;
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)dp[i][j]=-1;
    while(m--){
        scanf("%d%d%d%d",&l,&r,&a,&b);
        graph[l].PB({r,{a,b}});
    }
    dfs(1);
    printf("%d\n",f(1,1));
}
accuracy: 1
time_ms: 10
memory_kb: 6836
final_rank: 1

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 1000
#define HUGE_NUM 9999999999999999


struct Edge{
	Edge(int arg_to,ll arg_cost_1,ll arg_cost_2){
		to = arg_to;
		cost_1 = arg_cost_1;
		cost_2 = arg_cost_2;
	}
	int to;
	ll cost_1,cost_2;
};

struct State{
	State(int arg_node_1,int arg_node_2,ll arg_sum_cost){
		node_1 = arg_node_1;
		node_2 = arg_node_2;
		sum_cost = arg_sum_cost;
	}
	bool operator<(const struct State & arg) const{ //総コストの昇順(PQ)
		return sum_cost > arg.sum_cost;
	}
	int node_1,node_2;
	ll sum_cost;

};

int V,E;
int in_num[NUM],topo_order[NUM];
vector<Edge> G[NUM];
ll min_dist[NUM][NUM];


int main(){

	scanf("%d %d",&V,&E);

	int start = 0,goal = V-1;

	int from,to;
	ll cost_1,cost_2;

	for(int i = 0; i < V; i++)in_num[i] = 0;

	for(int loop = 0; loop < E; loop++){
		scanf("%d %d %lld %lld",&from,&to,&cost_1,&cost_2);
		from--;
		to--;
		in_num[to]++; //トポロジカル順序を計算するため
		G[from].push_back(Edge(to,cost_1,cost_2));
	}

	int index = 0,next_node;

	queue<int> Q;
	Q.push(start);

	//各ノードのトポロジカル順序を求める
	while(!Q.empty()){

		topo_order[Q.front()] = index++;

		for(int i = 0; i < G[Q.front()].size(); i++){
			next_node = G[Q.front()][i].to;
			in_num[next_node]--;

			if(in_num[next_node] == 0){
				Q.push(next_node);
			}
		}
		Q.pop();
	}

	for(int i = 0; i < V; i++){
		for(int k = 0; k < V; k++)min_dist[i][k] = HUGE_NUM; //min_dist[1回目の終端][2回目の終端] = 合計最短コスト
	}

	min_dist[start][start] = 0;
	priority_queue<State> PQ;
	PQ.push(State(start,start,0));

	int next_node_1,next_node_2,next_cost;

	while(!PQ.empty()){

		if(PQ.top().sum_cost > min_dist[PQ.top().node_1][PQ.top().node_2]){
			PQ.pop();
			continue;
		}

		if(PQ.top().node_1 == PQ.top().node_2){

			if(PQ.top().node_1 == goal){
				printf("%lld\n",PQ.top().sum_cost);
				return 0;
			}

			//同じエッジを下る場合
			for(int i = 0; i < G[PQ.top().node_1].size(); i++){

				next_node_1 = G[PQ.top().node_1][i].to;
				next_node_2 = next_node_1;
				next_cost = PQ.top().sum_cost+G[PQ.top().node_1][i].cost_1+G[PQ.top().node_1][i].cost_2;

				if(min_dist[next_node_1][next_node_2] > next_cost){
					min_dist[next_node_1][next_node_2] = next_cost;
					PQ.push(State(next_node_1,next_node_2,next_cost));
				}
			}


			if(G[PQ.top().node_1].size() == 1){
				PQ.pop();
				continue;
			}
			//違うエッジを下る場合
			for(int i = 0; i < G[PQ.top().node_1].size(); i++){

				next_node_1 = G[PQ.top().node_1][i].to;

				for(int k = 0; k < G[PQ.top().node_1].size(); k++){
					if(k == i)continue;

					next_node_2 = G[PQ.top().node_1][k].to;
					next_cost = PQ.top().sum_cost+G[PQ.top().node_1][i].cost_1+G[PQ.top().node_1][k].cost_1;

					if(min_dist[next_node_1][next_node_2] > next_cost){
						min_dist[next_node_1][next_node_2] = next_cost;
						PQ.push(State(next_node_1,next_node_2,next_cost));
					}
				}
			}

		}else{

			//トポロジカルソート順が小さい方のノードを進める
			if(topo_order[PQ.top().node_1] <= topo_order[PQ.top().node_2]){

				for(int i = 0; i < G[PQ.top().node_1].size(); i++){

					next_node_1 = G[PQ.top().node_1][i].to;
					next_node_2 = PQ.top().node_2;
					next_cost = PQ.top().sum_cost+G[PQ.top().node_1][i].cost_1;

					if(min_dist[next_node_1][next_node_2] > next_cost){
						min_dist[next_node_1][next_node_2] = next_cost;
						PQ.push(State(next_node_1,next_node_2,next_cost));
					}
				}

			}else{

				for(int i = 0; i < G[PQ.top().node_2].size(); i++){

					next_node_2 = G[PQ.top().node_2][i].to;
					next_node_1 = PQ.top().node_1;
					next_cost = PQ.top().sum_cost+G[PQ.top().node_2][i].cost_1; //★初めて通るとして良い★

					if(min_dist[next_node_1][next_node_2] > next_cost){
						min_dist[next_node_1][next_node_2] = next_cost;
						PQ.push(State(next_node_1,next_node_2,next_cost));
					}
				}
			}
		}
		PQ.pop();
	}

	return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 27272
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 1000
#define HUGE_NUM 9999999999999999


struct Edge{
	Edge(int arg_to,ll arg_cost_1,ll arg_cost_2){
		to = arg_to;
		cost_1 = arg_cost_1;
		cost_2 = arg_cost_2;
	}
	int to;
	ll cost_1,cost_2;
};

struct State{
	State(int arg_node_1,int arg_node_2,ll arg_sum_cost){
		node_1 = arg_node_1;
		node_2 = arg_node_2;
		sum_cost = arg_sum_cost;
	}
	bool operator<(const struct State & arg) const{ //総コストの昇順(PQ)
		return sum_cost > arg.sum_cost;
	}
	int node_1,node_2;
	ll sum_cost;

};

int V,E;
int in_num[NUM],topo_order[NUM];
vector<Edge> G[NUM];
ll min_dist[NUM][NUM];


int main(){

	scanf("%d %d",&V,&E);

	int start = 0,goal = V-1;

	int from,to;
	ll cost_1,cost_2;

	for(int i = 0; i < V; i++)in_num[i] = 0;

	for(int loop = 0; loop < E; loop++){
		scanf("%d %d %lld %lld",&from,&to,&cost_1,&cost_2);
		from--;
		to--;
		in_num[to]++; //トポロジカル順序を計算するため
		G[from].push_back(Edge(to,cost_1,cost_2));
	}

	int index = 0,next_node;

	queue<int> Q;
	Q.push(start);

	//各ノードのトポロジカル順序を求める
	while(!Q.empty()){

		topo_order[Q.front()] = index++;

		for(int i = 0; i < G[Q.front()].size(); i++){
			next_node = G[Q.front()][i].to;
			in_num[next_node]--;

			if(in_num[next_node] == 0){
				Q.push(next_node);
			}
		}
		Q.pop();
	}

	for(int i = 0; i < V; i++){
		for(int k = 0; k < V; k++)min_dist[i][k] = HUGE_NUM; //min_dist[1回目の終端][2回目の終端] = 合計最短コスト
	}

	min_dist[start][start] = 0;
	priority_queue<State> PQ;
	PQ.push(State(start,start,0));

	int next_node_1,next_node_2,next_cost;

	while(!PQ.empty()){

		if(PQ.top().sum_cost > min_dist[PQ.top().node_1][PQ.top().node_2]){
			PQ.pop();
			continue;
		}

		if(PQ.top().node_1 == PQ.top().node_2){

			//同じエッジを下る場合
			for(int i = 0; i < G[PQ.top().node_1].size(); i++){

				next_node_1 = G[PQ.top().node_1][i].to;
				next_node_2 = next_node_1;
				next_cost = PQ.top().sum_cost+G[PQ.top().node_1][i].cost_1+G[PQ.top().node_1][i].cost_2;

				if(min_dist[next_node_1][next_node_2] > next_cost){
					min_dist[next_node_1][next_node_2] = next_cost;
					PQ.push(State(next_node_1,next_node_2,next_cost));
				}
			}


			if(G[PQ.top().node_1].size() == 1){
				PQ.pop();
				continue;
			}
			//違うエッジを下る場合
			for(int i = 0; i < G[PQ.top().node_1].size(); i++){

				next_node_1 = G[PQ.top().node_1][i].to;

				for(int k = 0; k < G[PQ.top().node_1].size(); k++){
					if(k == i)continue;

					next_node_2 = G[PQ.top().node_1][k].to;
					next_cost = PQ.top().sum_cost+G[PQ.top().node_1][i].cost_1+G[PQ.top().node_1][k].cost_1;

					if(min_dist[next_node_1][next_node_2] > next_cost){
						min_dist[next_node_1][next_node_2] = next_cost;
						PQ.push(State(next_node_1,next_node_2,next_cost));
					}
				}
			}

		}else{

			//トポロジカルソート順が小さい方のノードを進める
			if(topo_order[PQ.top().node_1] <= topo_order[PQ.top().node_2]){

				for(int i = 0; i < G[PQ.top().node_1].size(); i++){

					next_node_1 = G[PQ.top().node_1][i].to;
					next_node_2 = PQ.top().node_2;
					next_cost = PQ.top().sum_cost+G[PQ.top().node_1][i].cost_1;

					if(min_dist[next_node_1][next_node_2] > next_cost){
						min_dist[next_node_1][next_node_2] = next_cost;
						PQ.push(State(next_node_1,next_node_2,next_cost));
					}
				}

			}else{

				for(int i = 0; i < G[PQ.top().node_2].size(); i++){

					next_node_2 = G[PQ.top().node_2][i].to;
					next_node_1 = PQ.top().node_1;
					next_cost = PQ.top().sum_cost+G[PQ.top().node_2][i].cost_1; //★初めて通るとして良い★

					if(min_dist[next_node_1][next_node_2] > next_cost){
						min_dist[next_node_1][next_node_2] = next_cost;
						PQ.push(State(next_node_1,next_node_2,next_cost));
					}
				}
			}
		}
		PQ.pop();
	}

	printf("%lld\n",min_dist[goal][goal]);

	return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 27236
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

constexpr ll inf = 1e18;

struct edge {
    int to;
    ll c1, c2;
};

using edges = vector<edge>;
using graph = vector<edges>;

int main() {
    int n, p;
    cin >> n >> p;
    graph g(n);
    for(int i = 0; i < p; ++i) {
        int s, e;
        ll t1, t2;
        cin >> s >> e >> t1 >> t2;
        g[s - 1].push_back(edge{e - 1, t1, t2});
    }

    vector<int> topo(n, -1);
    int idx = 0;
    function<void(int)> calc_topo = [&] (int v) {
        if(topo[v] != -1) return;
        for(auto& e : g[v]) {
            calc_topo(e.to);
        }
        topo[v] = idx++;
    };
    calc_topo(0);

    vector<vector<ll>> dist(n, vector<ll>(n, inf));
    dist[0][0] = 0;
    using state = tuple<ll, int, int>;
    priority_queue<state, vector<state>, greater<state>> que;
    que.emplace(0, 0, 0);
    while(!que.empty()) {
        ll cur_c;
        int fst_v, sec_v;
        tie(cur_c, fst_v, sec_v) = que.top();
        que.pop();
        if(fst_v == sec_v) {
            for(auto& e : g[fst_v]) {
                ll nxt_c = cur_c + e.c1 + e.c2;
                if(dist[e.to][e.to] > nxt_c) {
                    dist[e.to][e.to] = nxt_c;
                    que.emplace(nxt_c, e.to, e.to);
                }
            }

            for(auto& e1 : g[fst_v]) {
                for(auto& e2 : g[sec_v]) {
                    if(e1.to == e2.to) continue;
                    ll nxt_c = cur_c + e1.c1 + e2.c1;
                    if(dist[e1.to][e2.to] > nxt_c) {
                        dist[e1.to][e2.to] = nxt_c;
                        que.emplace(nxt_c, e1.to, e2.to);
                    }
                }
            }
        } else {
            if(topo[fst_v] > topo[sec_v]) {
                for(auto& e : g[fst_v]) {
                    ll nxt_c = cur_c + e.c1;
                    if(dist[e.to][sec_v] > nxt_c) {
                        dist[e.to][sec_v] = nxt_c;
                        que.emplace(nxt_c, e.to, sec_v);
                    }
                }
            } else {
                for(auto& e : g[sec_v]) {
                    ll nxt_c = cur_c + e.c1;
                    if(dist[fst_v][e.to] > nxt_c) {
                        dist[fst_v][e.to] = nxt_c;
                        que.emplace(nxt_c, fst_v, e.to);
                    }
                }
            }
        }
    }

    cout << dist[n - 1][n - 1] << endl;
}
accuracy: 1
time_ms: 240
memory_kb: 27316
final_rank: 14

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld =long double;
const ld eps = 1e-9;


struct edge {
	int from;
	int to;
	int c1;
	int c2;
};

int main()
{
	int N,M;cin>>N>>M;
	vector<vector<edge>>graph(N);
	vector<int>comes(N);
	for (int i = 0; i < M; ++i) {
		int a,b,t1,t2;cin>>a>>b>>t1>>t2;
		a--;b--;
		graph[a].push_back(edge{ a,b,t1,t2 });
		comes[b]++;
	}
	vector<int>v;
	vector<int>nums(N);
	{
		queue<int>que;
		for (int i = 0; i < N; ++i) {
			if (!comes[i])que.push(i);
		}
		while (!que.empty()) {
			int now(que.front());
			que.pop();
			v.push_back(now);
			for (auto e : graph[now]) {
				comes[e.to]--;
				if (!comes[e.to]) {
					que.push(e.to);
				}
			}
		}
		for (int i = 0; i < N; ++i) {
			nums[v[i]]=i;
		}
	}
	vector<vector<vector<int>>>memo(N,vector<vector<int>>(N,vector<int>(2,1e9)));
	memo[0][0][0]=0;

	for (int i = 0; i < N; ++i) {
		for (int j = 0; j <= i; ++j) {
			for (int k = 0; k < 2; ++k) {
				int now_u = v[j];
				int now_d = v[i];

				for (auto e : graph[now_u]) {
					if (k&&e.to == now_d)continue;
					else {
						int next_u = e.to;
						int next_d = now_d;

						if (nums[next_u]>nums[next_d])swap(next_u, next_d);

						int next_i = nums[next_d];
						int next_j = nums[next_u];

						memo[next_i][next_j][i==j] = min(memo[next_i][next_j][i==j], memo[i][j][k] + e.c1);
					}
				}
				if (now_u == now_d) {
					for (auto e : graph[now_u]) {

						int next_u = e.to;
						int next_d = e.to;


						int next_i = nums[next_d];
						int next_j = nums[next_u];

						memo[next_i][next_j][0] = min(memo[next_i][next_j][0], memo[i][j][k] + e.c1 + e.c2);

					}
				}
			}
			
		}
	}
	int ans=memo[N-1][N-1][0];
	ans=min(ans,memo[N-1][N-1][1]);
	cout<<ans<<endl;

	
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 58012
final_rank: 13