Problem:
E: いたずらされたグラフ
問題
あなたはグラフのアルゴリズムとして典型であるフローの問題を解いていた。
その問題で与えられるグラフは、頂点 $N$ 個、辺 $M$ 本であり、頂点 $x_i$ から 頂点 $y_i$ に容量 $z_i$ 、コスト $d_i$ の辺が張られている。
ところが、AORイカちゃんが入力ケースにいたずらした。
その結果、 $x_i, y_i, z_i$ の順序がシャッフルされ、頂点の情報と容量の情報が区別できなくなってしまった。
そこで、あなたは $s-t$ 間のフローを求めることを諦め、 $s-t$ 間の最短距離を求めることにした。
あなたは、 $x_i, y_i, z_i$ の順序がシャッフルされた入力ケース $a_i, b_i, c_i$ のうちから二つを頂点情報にし、コスト $d_i$ の辺を張ることにした。つまり、$a_i$ から $b_i$, $a_i$ から $c_i$, $b_i$ から $c_i$ の三つの候補のうち一つにコスト $d_i$ の辺を張る。
考えられるグラフのうち、 「s から t への最短距離」の最小値を求めよ。
制約
$2 \le N \le 10^5$
$1 \le M \le 10^5$
$1 \le s,t \le N$
$1 \le a_i,b_i,c_i \le N$
$1 \le d_i \le 10^9$
$s \neq t$
元のグラフにおいて $s$ から $t$ への経路が存在する
入力は全て整数
入力
$N \ M \ s \ t$
$a_1 \ b_1 \ c_1 \ d_1$
$\vdots$
$a_M \ b_M \ c_M \ d_M$
出力
考えられるグラフのうち、 「$s$ から $t$ への最短距離」の最小値を一行で出力せよ。また末尾に改行を出力せよ。
サンプル
サンプル入力 1
5 3 1 4
3 1 2 5
3 4 2 3
5 4 2 2
サンプル出力 1
7
サンプル入力 2
8 5 8 3
4 5 1 2
5 6 2 3
7 8 5 12
3 1 2 11
1 2 3 10
サンプル出力 2
24

Submitted solutions:

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <queue>
using namespace std;
typedef long long ll;
// const ll INF64 = 1LL << 60;
const ll INF64 = ((1LL<<62)-(1LL<<31));  // 10^18より大きく、かつ2倍しても負にならない数
const int INF32 = 0x3FFFFFFF;  // =(2^30)-1 10^9より大きく、かつ2倍しても負にならない数
template<class T> inline bool chmin(T &a, T b) { if(a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T &a, T b) { if(a < b) { a = b; return true; } return false; }
#define YesNo(T) cout << ((T) ? "Yes" : "No") << endl;  // T:bool

// AOJ 2878
// https://onlinejudge.u-aizu.ac.jp/challenges/sources/VPC/RUPC/2878?year=2018

/*
 * 問題文が微妙だが、辺は双方向と思って良さそう。
 * 3点a,b,cのうち2点を選んで辺を張るとのことだが、仮に3点でそれぞれ辺を張ったとしても
 * 最短経路がa->b->cのように3点を通るケースって無くない？となった。
 * ということで、3点で双方向に辺を張ってダイクストラ法をやって良さそう、と思って実装してAC.
 */

// 頂点を結ぶ辺
struct Edge
{
	int to;  // 隣接頂点番号
	ll weight;  // 辺の重み
	Edge(int to_, ll weight_) : to(to_), weight(weight_) {}
};
using Graph = vector<vector<Edge>>;
// 頂点sを起点にダイクストラ。
// distは未探索部分をINFで埋めていること。
// 探索結果として、distに頂点sを起点(=0)とした距離を格納する。
void dijkstra(Graph &G, int s, vector<ll> &dist)
{
	dist[s] = 0;
	using dist_v = pair<ll, int>;  // 距離とその頂点番号のpair
	priority_queue<dist_v, vector<dist_v>, greater<dist_v>> que;
	que.push({dist[s], s});

	while(!que.empty())
	{
		ll d = que.top().first;
		int v = que.top().second;
		que.pop();

		if(d > dist[v]) continue;  // {d, v}はゴミのためスルー

		// 頂点vから出ている各辺について探索
		for(auto &e : G[v])
		{
			ll d_next;
			// 頂点vと辺eを用いた先の頂点について、距離を求める。
			// 基本はdist[v]+e.weightで良いが、問題によっては＋αが必要。(ABC192-E,ABC204-E等)
			d_next = dist[v] + e.weight;
			if(dist[e.to] > d_next)
			{
				dist[e.to] = d_next;
				que.push({dist[e.to], e.to});
			}
		}
	}
}

int main(void)
{
	int i;
	int N, M; cin >> N >> M;
	int s, t; cin >> s >> t;
	s--; t--;
	Graph g(N);
	for(i = 0; i < M; i++)
	{
		int a, b, c, d; cin >> a >> b >> c >> d;
		a--; b--; c--;
		g[a].push_back({b, d});
		g[a].push_back({c, d});
		g[b].push_back({a, d});
		g[b].push_back({c, d});
		g[c].push_back({a, d});
		g[c].push_back({b, d});
	}
	vector<ll> dist(N, INF64);
	dijkstra(g, s, dist);
	cout << dist[t] << endl;

	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 26400
final_rank: 11

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <queue>
using namespace std;
typedef long long ll;
// const ll INF64 = 1LL << 60;
const ll INF64 = ((1LL<<62)-(1LL<<31));  // 10^18より大きく、かつ2倍しても負にならない数
const int INF32 = 0x3FFFFFFF;  // =(2^30)-1 10^9より大きく、かつ2倍しても負にならない数
template<class T> inline bool chmin(T &a, T b) { if(a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T &a, T b) { if(a < b) { a = b; return true; } return false; }
#define YesNo(T) cout << ((T) ? "Yes" : "No") << endl;  // T:bool

// AOJ 2878
// https://onlinejudge.u-aizu.ac.jp/challenges/sources/VPC/RUPC/2878?year=2018

/*
 * 
 * 
 * 問題文が微妙だが、辺は双方向と思って良さそう。
 * 
 * 
 */

// 頂点を結ぶ辺
struct Edge
{
	int to;  // 隣接頂点番号
	ll weight;  // 辺の重み
	Edge(int to_, ll weight_) : to(to_), weight(weight_) {}
};
using Graph = vector<vector<Edge>>;
// 頂点sを起点にダイクストラ。
// distは未探索部分をINFで埋めていること。
// 探索結果として、distに頂点sを起点(=0)とした距離を格納する。
void dijkstra(Graph &G, int s, vector<ll> &dist)
{
	dist[s] = 0;
	using dist_v = pair<ll, int>;  // 距離とその頂点番号のpair
	priority_queue<dist_v, vector<dist_v>, greater<dist_v>> que;
	que.push({dist[s], s});

	while(!que.empty())
	{
		ll d = que.top().first;
		int v = que.top().second;
		que.pop();

		if(d > dist[v]) continue;  // {d, v}はゴミのためスルー

		// 頂点vから出ている各辺について探索
		for(auto &e : G[v])
		{
			ll d_next;
			// 頂点vと辺eを用いた先の頂点について、距離を求める。
			// 基本はdist[v]+e.weightで良いが、問題によっては＋αが必要。(ABC192-E,ABC204-E等)
			d_next = dist[v] + e.weight;
			if(dist[e.to] > d_next)
			{
				dist[e.to] = d_next;
				que.push({dist[e.to], e.to});
			}
		}
	}
}

int main(void)
{
	int i;
	int N, M; cin >> N >> M;
	int s, t; cin >> s >> t;
	s--; t--;
	Graph g(N);
	for(i = 0; i < M; i++)
	{
		int a, b, c, d; cin >> a >> b >> c >> d;
		a--; b--; c--;
		g[a].push_back({b, d});
		g[a].push_back({c, d});
		g[b].push_back({a, d});
		g[b].push_back({c, d});
		g[c].push_back({a, d});
		g[c].push_back({b, d});
	}
	vector<ll> dist(N, INF64);
	dijkstra(g, s, dist);
	cout << dist[t] << endl;

	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 25968
final_rank: 10

code_snippet: #include <bits/stdc++.h>



using namespace std;

//make -f ../makefile SRC=

/*
TODO
*/


//------------------------------------------------------------------------------
bool DEBUG = false;
const int64_t INF = 1e18;
const int MAX_N = 100000;
static int64_t D[MAX_N];

//------------------------------------------------------------------------------
struct SEdge
{
    public:
    int w, c;
    SEdge(): w(-1), c(0) {}
    SEdge(int v2, int cost): w(v2), c(cost) {}
    void debug() const { printf("w=%d, c=%d\n", w, c); }
};

typedef vector<SEdge> SEdges;
typedef vector<SEdges> Graph;
//------------------------------------------------------------------------------
struct Node
{
    int v;
    int64_t d;
    bool operator==(const Node& other) const { return v==other.v && d==other.d; }
    // for PQ
    bool operator<(const Node& other) const { return d > other.d; }
    Node(): v(-1), d(INF) {}
    Node(int vert, int64_t _dist): v(vert), d(_dist) {}
};

typedef vector<Node> Nodes;
typedef priority_queue<Node,Nodes> PQ;


//------------------------------------------------------------------------------
int64_t dijkstra(int N, Graph& G, int src, int dest)
{
    //--------------------------------------------------------------------------
    // init:
    for (int v=0; v<N; ++v) { D[v] = INF; }
    D[src] = 0;
    PQ pq;
    pq.push(Node(src, 0));

    //--------------------------------------------------------------------------
    // search solution:
    while (!pq.empty())
    {
        Node node = pq.top(); pq.pop();
        int v = node.v;

        // for each neighbor w of v:
        for (auto e: G[v])
        {
            if (D[e.w] == INF || D[e.w] > D[v] + e.c)
            {
                D[e.w] = D[v] + e.c;
                pq.push( Node(e.w, D[e.w]) );
            }
        }
    }

    //--------------------------------------------------------------------------
    return D[dest];
}



void solve(int N, Graph& G, int src, int dest)
{
    int64_t res = dijkstra(N, G, src, dest);
    printf("%ld\n", res);
}
//------------------------------------------------------------------------------
int main()
{
    //DEBUG = true;
    //--------------------------------------------------------------------------
    int N, M, src, dest, v1, v2, v3, c, num;
    num = scanf("%d %d %d %d ", &N, &M, &src, &dest);
    src--;
    dest--;

    Graph G(N);
    for (int m=0; m<M; ++m)
    {
        num = scanf("%d %d %d %d ", &v1, &v2, &v3, &c);
        v1--;
        v2--;
        v3--;
        G[v1].push_back( SEdge(v2, c) );
        G[v1].push_back( SEdge(v3, c) );
        G[v2].push_back( SEdge(v1, c) );
        G[v2].push_back( SEdge(v3, c) );
        G[v3].push_back( SEdge(v1, c) );
        G[v3].push_back( SEdge(v2, c) );
    }
    solve(N, G, src, dest);
    //--------------------------------------------------------------------------
    return 0;
}
//------------------------------------------------------------------------------
accuracy: 1
time_ms: 50
memory_kb: 18064
final_rank: 1

code_snippet: #include <bits/stdc++.h>



using namespace std;

//make -f ../makefile SRC=

/*
TODO
*/


//------------------------------------------------------------------------------
bool DEBUG = false;
const int INF = 1000000000;

const int MAX_N = 100000;
static int D[MAX_N];

//------------------------------------------------------------------------------
struct SEdge
{
    public:
    int w, c;
    SEdge(): w(-1), c(INF) {}
    SEdge(int v2, int cost): w(v2), c(cost) {}
    void debug() const { printf("w=%d, c=%d\n", w, c); }
};

typedef vector<SEdge> SEdges;
typedef vector<SEdges> Graph;
//------------------------------------------------------------------------------
struct Node
{
    int v, d;

    bool operator==(const Node& other) const { return v==other.v && d==other.d; }
    // for PQ
    bool operator<(const Node& other) const { return d > other.d; }
    Node(): v(-1), d(INF) {}
    Node(int vert, int _dist): v(vert), d(_dist) {}
};

typedef vector<Node> Nodes;
typedef priority_queue<Node,Nodes> PQ;


//------------------------------------------------------------------------------
int dijkstra(int N, Graph& G, int src, int dest)
{
    //--------------------------------------------------------------------------
    // init:
    for (int v=0; v<N; ++v) { D[v] = INF; }
    D[src] = 0;
    PQ pq;
    pq.push(Node(src, 0));

    //--------------------------------------------------------------------------
    // search solution:
    while (!pq.empty())
    {
        Node node = pq.top(); pq.pop();
        int v = node.v;

        // for each neighbor w of v:
        for (auto e: G[v])
        {
            if (D[e.w] == INF || D[e.w] > D[v] + e.c)
            {
                D[e.w] = D[v] + e.c;
                pq.push( Node(e.w, D[e.w]) );
            }
        }
    }

    //--------------------------------------------------------------------------
    return D[dest];
}



void solve(int N, Graph& G, int src, int dest)
{
    int res = dijkstra(N, G, src, dest);
    printf("%d\n", res);
}
//------------------------------------------------------------------------------
int main()
{
    //DEBUG = true;
    //--------------------------------------------------------------------------
    int N, M, src, dest, v1, v2, v3, c, num;
    num = scanf("%d %d %d %d ", &N, &M, &src, &dest);
    src--;
    dest--;

    Graph G(N);
    for (int m=0; m<M; ++m)
    {
        num = scanf("%d %d %d %d ", &v1, &v2, &v3, &c);
        v1--;
        v2--;
        v3--;
        G[v1].push_back( SEdge(v2, c) );
        G[v1].push_back( SEdge(v3, c) );
        G[v2].push_back( SEdge(v1, c) );
        G[v2].push_back( SEdge(v3, c) );
        G[v3].push_back( SEdge(v1, c) );
        G[v3].push_back( SEdge(v2, c) );
    }
    solve(N, G, src, dest);
    //--------------------------------------------------------------------------
    return 0;
}
//------------------------------------------------------------------------------
accuracy: 0.09090909090909091
time_ms: 10
memory_kb: 7320
final_rank: 19

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <climits>

using namespace std;

void solve() {
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    s--;
    t--;

    vector<unordered_map<int, int>> graph(n);

    for (int i = 0; i < m; ++i) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a--;
        b--;
        c--;
        graph[a][b] = min(graph[a].count(b) ? graph[a][b] : INT_MAX, d);
        graph[b][a] = min(graph[b].count(a) ? graph[b][a] : INT_MAX, d);
        graph[a][c] = min(graph[a].count(c) ? graph[a][c] : INT_MAX, d);
        graph[c][a] = min(graph[c].count(a) ? graph[c][a] : INT_MAX, d);
        graph[b][c] = min(graph[b].count(c) ? graph[b][c] : INT_MAX, d);
        graph[c][b] = min(graph[c].count(b) ? graph[c][b] : INT_MAX, d);
    }
    
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;
    vector<long long> distances(n, 1LL << 60);
    
    pq.push({0, s});
    distances[s] = 0;

    while (!pq.empty()) {
        long long dist = pq.top().first;
        int node = pq.top().second;
        pq.pop();
        if (dist > distances[node]) {
            continue;
        }
        for (const auto& neighbor : graph[node]) {
            int next_node = neighbor.first;
            int weight = neighbor.second;

            if (dist + weight < distances[next_node]) {
                distances[next_node] = dist + weight;
                pq.push({dist + weight, next_node});
            }
        }
    }

    if (distances[t] == (1LL << 60)) {
        cout << -1 << endl;  // should never happen but we never know
    } else {
        cout << distances[t] << endl;
    }
}

int main() {
    solve();
    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 38588
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) (a).begin(), a.end()
#define rep(i,n) for(ll i = 0; i < n; i++)

int main(){
    int n,m,s,t;
    cin >> n >> m >> s >> t;
    s--,t--;
    vector<vector<pair<int,ll>>> g(n);
    rep(i,m){
        int a,b,c,d;
        cin >> a >> b >> c >> d;
        a--,b--,c--;
        g[a].emplace_back(b,d);
        g[a].emplace_back(c,d);
        g[b].emplace_back(a,d);
        g[b].emplace_back(c,d);
        g[c].emplace_back(a,d);
        g[c].emplace_back(b,d);
    }

    vector<ll> dp(n, 1e18);
    dp[s] = 0;
    priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> q;
    q.push({0, s});

    while(q.size()){
        auto [c, p] = q.top();
        q.pop();
        if(dp[p] != c) continue;
        for(auto [to, cst] : g[p]){
            if(dp[to] > dp[p] + cst){
                dp[to] = dp[p] + cst;
                q.push({dp[to], to});
            }
        }
    }

    cout << dp[t] << endl;
}
accuracy: 1
time_ms: 110
memory_kb: 24708
final_rank: 9

code_snippet: /*#include<atcoder/all>
using namespace atcoder;*/

#include <bits/stdc++.h>
template<class T> inline bool chmin(T&a, T b){if(a > b){a = b; return true;}else{return false;}}
template<class T> inline bool chmax(T&a, T b){if(a < b){a = b; return true;}else{return false;}}
#define ll long long
#define double long double
#define rep(i,n) for(int i=0;i<(n);i++)
#define REP(i,n) for(int i=1;i<=(n);i++)
#define mod (ll)(1e9+7)
#define inf (ll)(3e18+7)
#define eps (double)(1e-9)
#define pi (double) acos(-1)
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
using namespace std;

struct edge{
  ll to, cost;
};

vector<vector<edge>> G(200010);
vector<ll> d(200010, inf);

#define P pair<int, int>
void dijkstra(int s) {
	priority_queue<P, vector<P>, greater<P>>que;
	d[s] = 0;
	que.push(P(0, s));
	while (!que.empty()) {
		P p = que.top(); que.pop();
		int v = p.second;
		if (d[v] < p.first)continue;
		rep(i, G[v].size()) {
			edge e = G[v][i];
			if (d[e.to] > d[v] + e.cost) {
				d[e.to] = d[v] + e.cost;
				que.push(P(d[e.to], e.to));
			}
		}
	}
}

int main(){
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    rep(i, m){
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a--; b--; c--;
        G[n+i].push_back({a, d});
        G[n+i].push_back({b, d});
        G[n+i].push_back({c, d});
        G[a].push_back({n+i, d});
        G[b].push_back({n+i, d});
        G[c].push_back({n+i, d});
    }

    dijkstra(s-1);

    cout << d[t-1] / 2 << endl;
}
accuracy: 1
time_ms: 640
memory_kb: 31104
final_rank: 18

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

typedef long long ll;

#define rep(i, s, n) for (int i = (int)(s); i < (int)(n); i++)
#define rrep(i, s, n) for (int i = (int)(n)-1; i >= (int)(s); i--)

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

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

template <typename T> T max(vector<T> &a){
	assert(!a.empty());
	T ret = a[0];
	for (int i=0; i<(int)a.size(); i++) chmax(ret, a[i]);
	return ret;
}

template <typename T> T min(vector<T> &a){
	assert(!a.empty());
	T ret = a[0];
	for (int i=0; i<(int)a.size(); i++) chmin(ret, a[i]);
	return ret;
}

template <typename T> T sum(vector<T> &a){
	T ret = 0;
	for (int i=0; i<(int)a.size(); i++) ret += a[i];
	return ret;
}

int main(){

	int n, m; cin >> n >> m;
	int s, t; cin >> s >> t; s--; t--;
	vector<int> a(m), b(m), c(m);
	vector ikeru(n, vector<pair<int,ll>>(0));
	rep(i,0,m){
		cin >> a[i] >> b[i] >> c[i];
		a[i]--; b[i]--; c[i]--;
		ll d; cin >> d;
		ikeru[a[i]].push_back(pair(b[i], d));
		ikeru[a[i]].push_back(pair(c[i], d));
		ikeru[b[i]].push_back(pair(c[i], d));
		ikeru[b[i]].push_back(pair(a[i], d));
		ikeru[c[i]].push_back(pair(a[i], d));
		ikeru[c[i]].push_back(pair(b[i], d));
	}	
	vector<ll> d(n, 1e18);
	d[s] = 0;
	priority_queue<pair<ll,int>> pq;
	pq.push(pair(0, s));
	while(!pq.empty()){
		auto [tmp, i] = pq.top();
		pq.pop();
		tmp = -tmp;
		if (tmp > d[i]) continue;
		for (auto [j, cost]: ikeru[i]){
			if (chmin(d[j], cost + tmp)){
				pq.push(pair(-d[j], j));
			}
		}
	}
	cout << d[t] << '\n';
}
accuracy: 1
time_ms: 110
memory_kb: 26416
final_rank: 12

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

using ll = long long;
using ld = long double;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<ll>>;

struct Edge {
    int from;
    int to;
    ll weight;
};

struct Graph {
    int n;
    int m;
    vector<Edge> edges;
    vector<vector<Edge>> adj;
};

// 無向辺 0-indexed
void add_edge(Graph &g, int from, int to, ll weight) {
    g.adj[from].push_back(Edge{from, to, weight});
    g.adj[to].push_back(Edge{to, from, weight});
    g.edges.push_back(Edge{from, to, weight});
}

// 有向辺 0-indexed
void add_directed_edge(Graph &g, int from, int to, ll weight) {
    g.adj[from].push_back(Edge{from, to, weight});
    g.edges.push_back(Edge{from, to, weight});
}

// 累積和 1-indexed
// cumsum[i] = v[0] + v[1] + ... + v[i - 1]
template <class T> vector<T> cumsum(vector<T> &v) {
    vector<T> ret(v.size() + 1, 0);
    for (int i = 0; i < v.size(); i++) {
        ret[i + 1] = ret[i] + v[i];
    }
    return ret;
}

#define overload4(_1, _2, _3, _4, name, ...) name
#define rep1(n) for (int i = 0; i < n; ++i)             // i: [0, n)
#define rep2(i, n) for (int i = 0; i < n; ++i)          // i: [0, n)
#define rep3(i, a, b) for (int i = a; i < b; ++i)       // i: [a, b)
#define rep4(i, a, b, c) for (int i = a; i < b; i += c) // i: [a, b) step c
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)
#define all(v) (v).begin(), (v).end()

const ll MOD = 998244353;
const ll MOD17 = 1000000007;
const ld PI = M_PI;
const ll INF = 1LL << 62;

const vector<char> abc = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
                          'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
                          's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

struct Data {
    ll best;
    ll mod;
};

vector<ll> dijkstra(Graph &g, int x) {
    priority_queue<tuple<ll, int>> que;
    que.push(make_tuple(0, x));
    vector<ll> d(g.n + 3, 9e15);
    d[x] = 0;
    while (!que.empty()) {
        auto [cost, v] = que.top();
        cost *= -1;
        que.pop();
        if (cost > d[v])
            continue;
        for (Edge e : g.adj[v]) {
            if (d[e.to] > d[v] + e.weight) {
                d[e.to] = d[v] + e.weight;
                que.push(make_tuple(-d[e.to], e.to));
            }
        }
    }
    for (int i = 0; i < d.size(); i++) {
        if (d[i] == 9e15)
            d[i] = -1;
    }
    return d;
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    s--;
    t--;
    Graph g;
    g.n = n;
    g.m = 3 * m;
    g.adj.resize(n);
    rep(m) {
        int a, b, c;
        ll d;
        cin >> a >> b >> c >> d;
        a--;
        b--;
        c--;
        add_edge(g, a, b, d);
        add_edge(g, b, c, d);
        add_edge(g, c, a, d);
    }

    auto d1 = dijkstra(g, s);
    cout << d1[t] << '\n';
}
accuracy: 1
time_ms: 70
memory_kb: 31056
final_rank: 16

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

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int N,M,S,T;
  cin>>N>>M>>S>>T;
  --S,--T;
  vector G(N,vector(0,array<ll,2>()));
  for(int i=0;i<M;i++){
    int A,B,C,D;
    cin>>A>>B>>C>>D;
    --A,--B,--C;
    G[A].push_back({B,D});
    G[A].push_back({C,D});
    G[B].push_back({A,D});
    G[B].push_back({C,D});
    G[C].push_back({A,D});
    G[C].push_back({B,D});
  }
  priority_queue<array<ll,2>,vector<array<ll,2>>,greater<array<ll,2>>>pq;
  vector dist(N,(ll)1e18);
  dist[S]=0;
  pq.push({0,S});
  while(pq.size()){
    auto [d,v]=pq.top();
    pq.pop();
    if(d>dist[v])continue;
    for(auto [u,c]:G[v]){
      if(dist[u]>d+c){
        dist[u]=d+c;
        pq.push({d+c,u});
      }
    }
  }
  cout<<dist[T]<<'\n';
}
accuracy: 1
time_ms: 60
memory_kb: 25064
final_rank: 4

code_snippet: #include <bits/stdc++.h>

#define rep(i,s,n) for(int i = int(s); i < int(n); i++)
#define rrep(i,s,n) for(int i = int(n) - 1; i >= int(s); i--)
#define all(v) (v).begin(), (v).end()

using ll = long long;

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

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

const ll INF = std::numeric_limits<ll>::max() / 4;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n,m,s,t;
    std::cin >> n >> m >> s >> t;
    s--; t--;
    std::vector g(n, std::vector<std::pair<int,ll>>());
    rep(i,0,m) {
        int a,b,c;
        ll d;
        std::cin >> a >> b >> c >> d;
        a--;
        b--;
        c--;
        g[a].emplace_back(b, d);
        g[a].emplace_back(c, d);
        g[b].emplace_back(a, d);
        g[b].emplace_back(c, d);
        g[c].emplace_back(a, d);
        g[c].emplace_back(b, d);
    }
    using P = std::pair<ll, int>;
    std::priority_queue<P, std::vector<P>, std::greater<P>> que;
    que.push({0, s});
    std::vector<ll> dp(n, INF);
    dp[s] = 0;
    while(!que.empty()) {
        auto [ret, v] = que.top();
        que.pop();
        if(dp[v] < ret) continue;
        for(auto [nv, cost]: g[v]) {
            if(chmin(dp[nv], dp[v] + cost)) {
                que.push({dp[nv], nv});
            }
        }
    }
    std::cout << dp[t] << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 24464
final_rank: 3

code_snippet: #include <bits/stdc++.h>
// #include <atcoder/all>
// // using mint = atcoder::modint998244353;
// using mint = atcoder::modint1000000007;
// using namespace atcoder;
using namespace std;

using ll = long long;
using vi = vector<int>;
// using vm = vector<mint>;
using vvi = vector<vi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using vpi = vector<pair<int,int>>;
using vpl = vector<pair<ll,ll>>;
#define rep(i,n) for (ll i = 0; i < n; i++)
#define replr(i,l,r) for (ll i = l; i < r; i++)
set<char> abc = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
const int inf =1e9;
const ll infl = 4e18;

template <typename T>
bool chmax(T &a, const T& b) {if (a < b) {a = b;  return true;}return false;}
template <typename T>
bool chmin(T &a, const T& b) {if (a > b) {a = b;  return true;}return false;}
template <typename T>
T max(vector<T> &v) {T m = 0;for (auto x : v) chmax(m, x);return m;}
template <typename T>
T min(vector<T> &v) {T m = inf;for (auto x : v) chmin(m, x);return m;}
template <typename T>
void print(vector<T> &v){for(auto x : v){cout<<x<<' ';}cout<<'\n';}
/*memo

*/

int main(){
    int N,M,s,t; cin >> N >> M >> s >> t;
    s--;t--;
    vector<vector<pair<int,ll>>> G(N);
    rep(i,M){
        int a,b,c,d; cin >> a >> b >> c >> d;
        a--;b--;c--;
        G[a].push_back({b,d});
        G[b].push_back({a,d});
        G[b].push_back({c,d});
        G[c].push_back({b,d});
        G[c].push_back({a,d});
        G[a].push_back({c,d});
    }
    vector<ll> dist(N,infl);
    dist[s]=0;
    priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> pq;
    pq.push({0,s});
    while(!pq.empty()){
        auto [d,v] = pq.top(); pq.pop();
        if (dist[v] < d) continue;
        for (auto [nv,nd] : G[v]){
            if (chmin(dist[nv],dist[v]+nd)){
                pq.push({dist[nv],nv});
            }
        }
    }
    if (dist[t]==infl) cout << -1 << endl;
    else cout << dist[t] << endl;
}
accuracy: 1
time_ms: 110
memory_kb: 24488
final_rank: 8

code_snippet: // SPDX-License-Identifier: MIT
// (c) 2023 TwoSquirrels
// my AtCoder environment: https://github.com/TwoSquirrels/atcoder-env

//#define DEBUG

// enable debug mode when compiled with -DDEBUG
#ifdef DEBUG
#  define IS_DEBUG (1)
#else
// QCFium method
#  pragma GCC target("avx2")
#  pragma GCC optimize("O3")
#  pragma GCC optimize("unroll-loops")
#  pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#  define IS_DEBUG (0)
#endif

/// includes

// standard libraries
#if __has_include(<bits/stdc++.h>)
#  include <bits/stdc++.h>
#else // <bits/stdc++.h>
// C++17 (clang)
#  include <cassert>
#  include <cfenv>
#  include <cfloat>
#  include <ciso646>
#  include <clocale>
#  include <csetjmp>
#  include <csignal>
#  include <cstdbool>
#  include <cinttypes>
#  include <charconv>
#  include <typeindex>
#  include <any>
#  include <scoped_allocator>
#  include <forward_list>
#  include <list>
#  include <map>
#  include <set>
#  include <valarray>
#  include <variant>
#  include <unordered_map>
#  include <unordered_set>
#  include <queue>
#  include <condition_variable>
#  include <shared_mutex>
#  include <codecvt>
#  include <future>
#  include <regex>
#  include <iostream>
#  include <random>
#  include <ctgmath>
#  include <fstream>
#endif // <bits/stdc++.h>

/// abi
#if __has_include(<cxxabi.h>)
#  define INCLUDED_CXXABI
#  include <cxxabi.h>
#endif // <cxxabi.h>

// boost libraries
#if __has_include(<boost/multiprecision/cpp_int.hpp>)
#  define INCLUDED_BOOST_CPP_INT
#  include <boost/multiprecision/cpp_int.hpp>
#endif
#if __has_include(<boost/math/special_functions/prime.hpp>)
#  define INCLUDED_BOOST_PRIME
#  include <boost/math/special_functions/prime.hpp>
#endif
#if __has_include(<boost/multiprecision/miller_rabin.hpp>)
#  define INCLUDED_BOOST_MILLER_RABIN
#  include <boost/multiprecision/miller_rabin.hpp>
#endif

// atcoder libraries
#if __has_include(<atcoder/all>)
#  define INCLUDED_ACL
#  include <atcoder/all>
#endif

/// sfinae

// is_pair
template <typename T> inline constexpr bool is_pair_v = false;
template <typename T, typename U> inline constexpr bool is_pair_v<std::pair<T, U>> = true;

// is_tuple
template <typename T> inline constexpr bool is_tuple_v = false;
template <typename... Types> inline constexpr bool is_tuple_v<std::tuple<Types...>> = true;

// istreamable
#if __cplusplus >= 202002L
template <typename T> concept istreamable_v = requires (T a) { std::cin >> a; };
#else // C++20
template<typename T, typename = void> inline constexpr bool istreamable_v = false;
template<typename T>
inline constexpr bool istreamable_v<T, std::void_t<decltype(std::cin >> std::declval<T&>())>> = true;
#endif // C++20

// ostreamable
#if __cplusplus >= 202002L
template <typename T> concept ostreamable_v = requires (T a) { std::cout << a; };
#else // C++20
template<typename T, typename = void> inline constexpr bool ostreamable_v = false;
template<typename T>
inline constexpr bool ostreamable_v<T, std::void_t<decltype(std::cout << std::declval<T&>())>> = true;
#endif // C++20

// iterable
#if __cplusplus >= 202002L
#  if __has_include(<ranges>)
template <typename T> concept iterable_v = std::ranges::range<T>;
#  else // <ranges>
template <typename T> concept iterable_v = requires (T a) { std::begin(a); std::end(a); };
#  endif // C++20
#else // C++20
template <typename T> inline constexpr bool iterable_v =
  std::is_same_v<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>()))>;
#endif // C++20

/// utils

template <typename T> inline std::string get_typename(std::size_t length_limit = std::string::npos) {
  std::string name;
#ifdef INCLUDED_CXXABI
  name = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
#else // INCLUDED_CXXABI
  name = typeid(T).name();
#endif // INCLUDED_CXXABI
#ifdef __ANDROID__
  name = std::regex_replace(name, std::regex("::__ndk1::"), "::");
#endif // __ANDROID__
  if (name.length() > length_limit) name = name.substr(0, length_limit - 3) + "...";
  return name;
}

template <typename T> constexpr T inf() {
  if constexpr (std::numeric_limits<T>::has_infinity) return std::numeric_limits<T>::infinity();
  return std::numeric_limits<T>::max() / 2.125L;
}

template <typename T> constexpr int sin90(T theta90) {
  if (theta90 % 2 == 0) return 0;
  return (theta90 % 4 + 4) % 4 < 2 ? 1 : -1;
}
template <typename T> constexpr int cos90(T theta90) {
  return sin90(theta90 + 1);
}
template <typename T> constexpr int sin45(T theta45) {
  if (theta45 % 4 == 0) return 0;
  return (theta45 % 8 + 8) % 8 < 4 ? 1 : -1;
}
template <typename T> constexpr int cos45(T theta45) {
  return sin45(theta45 + 2);
}

template <typename T, typename U> inline bool chmin(T &&a, const U b) {
  const bool compare = a > b;
  if (compare) a = b;
  return compare;
}
template <typename T, typename U> inline bool chmax(T &&a, const U b) {
  const bool compare = a < b;
  if (compare) a = b;
  return compare;
}

long long powi(int base, int exponent = 2) {
  long long ans = 1;
  for (int i = exponent; i != 0; i += (i >= 0 ? -1 : 1)) {
    if (i >= 0) ans *= base;
    else ans /= base;
    if (ans == 0) break;
  }
  return ans;
}

#ifdef INCLUDED_ACL
template <typename T = atcoder::modint>
T mint_inv(T x) {
  constexpr int memo_limit = 1 << 24;
  static std::array<T, memo_limit> memo;
  if (x.val() >= memo_limit) return x.inv();
  if (memo[x.val()] == 0) memo[x.val()] = x.inv();
  return memo[x.val()];
}
#endif // INCLUDED_ACL

template <typename T> bool is_prime(T n) {
  if (n <= 1) return false;
  if (n == 2 || n == 3) return true;
  if (n % 2 == 0 || n % 3 == 0) return false;
  // miller rabin
#ifdef INCLUDED_ACL
  if (n <= std::min(1LL << 32, static_cast<long long>(std::numeric_limits<int>::max()))) {
    return atcoder::internal::is_prime_constexpr(n);
  }
#endif // INCLUDED_ACL
#ifdef INCLUDED_BOOST_MILLER_RABIN
  return boost::multiprecision::miller_rabin_test(n, 25);
#endif // INCLUDED_BOOST_MILLER_RABIN
  // binary search
#ifdef INCLUDED_BOOST_PRIME
  if (n <= boost::math::prime(boost::math::max_prime)) {
    int left = 0, right = boost::math::max_prime + 1;
    while (right - left > 1) {
      auto mid = (left + right) / 2;
      (boost::math::prime(mid) <= n ? left : right) = mid;
    }
    return n == boost::math::prime(left);
  }
#endif // INCLUDED_BOOST_PRIME
  // trial
  T tried = 3;
#ifdef INCLUDED_BOOST_PRIME
  for (int i = 2; i <= int(boost::math::max_prime); i++) {
    const auto prime_i = boost::math::prime(i);
    if (prime_i > n / prime_i) return true;
    if (n % prime_i == 0) return false;
    tried = prime_i;
  }
#endif // INCLUDED_BOOST_PRIME
  for (T i = (tried + 5) / 6 * 6; (i - 1) * (i - 1) <= n; i += 6) {
    if (n % (i - 1) == 0 || n % (i + 1) == 0) return false;
  }
  return true;
}

// thanks to https://perogram.hateblo.jp/entry/2019/03/29/193632
template <bool osa_k = false, typename T> std::vector<std::pair<T, int>> factors(T n) {
  constexpr int spf_limit = 1 << 24;
  std::vector<std::pair<T, int>> result;
  if (n < 0) {
    result.emplace_back(-1, 1);
    const auto natural = factors<osa_k>(-n);
    result.insert(result.end(), natural.begin(), natural.end());
  } else if (n == 0) result.emplace_back(0, 1);
  else if (n == 1);
  else if (osa_k && n < spf_limit) {
    static std::array<int, spf_limit> spf;
    if (spf[0] == 0) {
      for (int i = 0; i < spf_limit; i++) spf[i] = i % 2 == 0 ? 2 : i % 3 == 0 ? 3 : i;
      spf[0] = 1;
      for (int p1 = 6; (p1 - 1) * (p1 - 1) <= spf_limit; p1 += 6) {
        if (spf[p1 - 1] == p1 - 1) for (int i = p1 - 1; i < spf_limit; i += p1 - 1) if (spf[i] == i) spf[i] = p1 - 1;
        if (spf[p1 + 1] == p1 + 1) for (int i = p1 + 1; i < spf_limit; i += p1 + 1) if (spf[i] == i) spf[i] = p1 + 1;
      }
    }
    while (n != 1) {
      if (!result.empty() && result.back().first == spf[n]) result.back().second++;
      else result.emplace_back(spf[n], 1);
      n /= spf[n];
    }
  } else {
    int expo = 0;
    while (n % 2 == 0) { n /= 2; expo++; }
    if (expo != 0) result.emplace_back(2, expo);
    expo = 0;
    while (n % 3 == 0) { n /= 3; expo++; }
    if (expo != 0) result.emplace_back(3, expo);
    T tried = 3;
#ifdef INCLUDED_BOOST_PRIME
    for (int i = 2; i <= int(boost::math::max_prime); i++) {
      const auto prime_i = boost::math::prime(i);
      if (prime_i > n / prime_i) break;
      expo = 0;
      while (n % prime_i == 0) { n /= prime_i; expo++; }
      result.emplace_back(prime_i, expo);
      tried = prime_i;
    }
    if (osa_k && n < spf_limit) {
      const auto rest = factors<osa_k>(n);
      result.insert(result.end(), rest.begin(), rest.end());
      n = 1;
    }
#endif // INCLUDED_BOOST_PRIME
    if (is_prime(n)) { result.emplace_back(n, 1); n = 1; }
    for (T i = (tried + 5) / 6 * 6; (i - 1) * (i - 1) <= n; i += 6) {
      expo = 0;
      while (n % (i - 1) == 0) { n /= (i - 1); expo++; }
      if (expo != 0) result.emplace_back(i - 1, expo);
      expo = 0;
      while (n % (i + 1) == 0) { n /= (i + 1); expo++; }
      if (expo != 0) result.emplace_back(i + 1, expo);
      if (osa_k && n < spf_limit) {
        const auto rest = factors<osa_k>(n);
        result.insert(result.end(), rest.begin(), rest.end());
        n = 1;
      }
    }
    if (n != 1) result.emplace_back(n, 1);
  }
  return result;
}

template <bool osa_k = false, typename T> std::vector<T> divisors(T n) {
  std::vector<T> result(1, 1);
  for (auto [prime, expo] : factors<osa_k>(n)) {
    const int result_size = result.size();
    T pow_i = 1;
    for (int i = 1; i <= expo; i++) {
      pow_i *= prime;
      for (int k = 0; k < result_size; k++) result.emplace_back(result[k] * pow_i);
    }
  }
  std::sort(result.begin(), result.end());
  return result;
}

template <typename T> T fact(int n, bool inv = false) {
  assert(n >= 0);
  static std::vector<std::pair<T, T>> factorials = { { 1, 1 } };
  for (int i = factorials.size(); i <= n; i++) factorials.emplace_back(i * factorials[i - 1].first, 0);
  if (inv && factorials[n].second == 0) {
    if constexpr (std::is_integral_v<T>) factorials[n].second = factorials[n].first <= 1 ? 1 : 0;
#ifdef INCLUDED_ACL
    else if constexpr (atcoder::internal::is_modint<T>::value) factorials[n].second = mint_inv(factorials[n].first);
#endif // INCLUDED_ACL
    else factorials[n].second = 1 / factorials[n].first;
  }
  return inv ? factorials[n].second : factorials[n].first;
}
template <typename T> T perm(int n, int k) { return fact<T>(n) * fact<T>(n - k, true); }
template <typename T> T comb(int n, int k) { return perm<T>(n, k) * fact<T>(k, true); }

// TODO: compressor
/*template <typename T> struct compressor {
  std::vector<T> positions;
  compressor() = default;
  compressor(const std::vector<T> &initial_pos) {
    
  }
};*/

template <typename T> std::vector<std::vector<T>> rotate(std::vector<std::vector<T>> grid, int angle = 1) {
  angle %= 4;
  if (angle == 0) return grid;
  auto h = grid.size(), w = grid[0].size();
  auto rotated = std::vector(w, std::vector<T>(h));
  for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) rotated[w - 1 - x][y] = grid[y][x];
  return rotate(rotated, angle - 1);
}

std::string int128_to_str(__int128_t target) {
  std::string target_str;
  __uint128_t target_tmp = target < 0 ? -target : target;
  do {
    target_str += '0' + target_tmp % 10;
    target_tmp /= 10;
  } while (target_tmp != 0);
  if (target < 0) target_str += '-';
  std::reverse(target_str.begin(), target_str.end());
  return target_str;
}

template <typename T> std::string to_pretty_str(T target) {
  using namespace std;
  string str;
  if constexpr (is_void_v<T>) str += "void"s;
  else if constexpr (is_null_pointer_v<T>) str += "null"s;
  else if constexpr (is_same_v<T, bool>) str += target ? "true"s : "false"s;
  else if constexpr (is_same_v<T, char> || is_same_v<T, char16_t> || is_same_v<T, char32_t> || is_same_v<T, wchar_t>) {
    str += "'"s + target + "'"s;
#ifdef INCLUDED_ACL
    } else if constexpr (atcoder::internal::is_modint<T>::value) {
    str += to_string(target.val()) + "(mod)"s;
#endif // INCLUDED_ACL
  } else if constexpr (is_arithmetic_v<T>) {
    if constexpr (is_same_v<T, __int128_t>) str += int128_to_str(target);
    else str += to_string(target);
    if constexpr (is_unsigned_v<T>) str += "u"s;
    if constexpr (is_same_v<remove_cv_t<T>, long>) str += "L"s;
    else if constexpr (is_same_v<remove_cv_t<T>, long long>) str += "LL"s;
    else if constexpr (is_same_v<T, __int128_t>) str += "LLL"s;
  } else if constexpr (is_pair_v<T>) {
    str += "("s + to_pretty_str(target.first);
    str += ", "s + to_pretty_str(target.second) + ")"s;
  } else if constexpr (is_convertible_v<T, string>) {
    str += "\""s + target + "\""s;
  } else if constexpr (is_array_v<T>) {
    str += "["s;
    bool separate = false;
    for (const auto &target_i : target) {
      if (separate) str += ", "s;
      str += to_pretty_str(target_i);
      separate = true;
    }
    str += "]"s;
  } else if constexpr (iterable_v<T>) {
    str += get_typename<T>(20) + "{"s;
    bool separate = false;
    for (const auto &target_i : target) {
      if (separate) str += ","s;
      str += " "s + to_pretty_str(target_i);
      separate = true;
    }
    if (separate) str += " "s;
    str += "}"s;
  } else {
    str += "<"s + get_typename<T>(20);
    str += " ("s + to_string(sizeof(target)) + " byte)>"s;
  }
  return str;
}

// input
#ifdef DEBUG
std::chrono::milliseconds input_total_ms{0};
#endif // DEBUG
template <typename T> inline void read_stdin(T &&target) {
#ifdef DEBUG
  using namespace std::chrono;
  const auto start = system_clock::now();
  std::cin >> target;
  const auto end = system_clock::now();
  input_total_ms += duration_cast<milliseconds>(end - start);
#else // DEBUG
  std::cin >> target;
#endif // DEBUG
}
template <typename T> inline T input(T &&target) {
  using T_V = std::remove_reference_t<T>;
  if constexpr (istreamable_v<T_V>) read_stdin(target);
  else if constexpr (iterable_v<T_V>) for (auto &&target_i : target) input(target_i);
  else if constexpr (is_pair_v<T_V>) {
    input(target.first);
    input(target.second);
  } else if constexpr (std::is_convertible_v<long long, T_V>) {
    long long n;
    target = input(n);
  } else {
#ifdef DEBUG
    std::cerr << "[WARN] Type " << get_typename<T_V>()
              << " is invalid, so input is skipped;" << std::endl;
#endif //DEBUG
  }
  return target;
}
// input and initialize
struct Scanner { template <typename T> inline operator T() const { T target; return input(target); } } scan;

// output
template <typename T> inline void write_stdout(T target, bool flush = false) {
  std::cout << target;
  if (flush) std::cout << std::flush;
}
template <typename T, typename Sep = char> inline void output(T target, Sep separator = ' ', bool flush = false) {
  if constexpr (ostreamable_v<T>) {
    write_stdout(target, flush);
  } else if constexpr (std::is_convertible<T, __int128_t>::value) {
    write_stdout(int128_to_str(target), flush);
#  ifdef INCLUDED_ACL
    } else if constexpr (atcoder::internal::is_modint<T>::value) {
    output(target.val(), separator, flush);
#  endif // INCLUDED_ACL
  } else if constexpr (iterable_v<T>) {
    bool separate = false;
    for (const auto target_i : target) {
      if (separate) write_stdout(separator);
      output(target_i, separator);
      separate = true;
    }
    if (flush) write_stdout("", flush);
  } else if constexpr (is_pair_v<T>) {
    output(target.first, separator);
    write_stdout(separator);
    output(target.second, separator, flush);
  } else {
    write_stdout("<unknown>", flush);
  }
}
template <typename T, typename Sep = char> inline void outputln(T target, Sep separator = ' ', bool flush = false) {
  output(target, separator);
  write_stdout('\n', flush);
}

// debug output
#ifdef DEBUG
std::chrono::milliseconds debug_total_ms{0};
template <typename F> void debug_txt_f(F callback, int line = -1, std::string file = (__FILE__)) {
  using namespace std::chrono;
  const auto start = system_clock::now();
  std::string dump_str = "[DEBUG] ";
  if (line >= 0) {
    dump_str += "(";
    if (file != (__FILE__)) dump_str += file + ":";
    dump_str += "L" + std::to_string(line) + ") ";
  }
  dump_str += callback();
  std::cerr << dump_str << std::endl;
  const auto end = system_clock::now();
  debug_total_ms += duration_cast<milliseconds>(end - start);
}
#  define debug_txt(txt) (debug_txt_f([]() { return to_pretty_str(txt); }, (__LINE__), (__FILE__)), true)
template <typename... Types>
void dump_f(std::string labels, std::tuple<Types...> targets_tupl, int line = -1, std::string file = (__FILE__)) {
  debug_txt_f([=]() {
    std::string txt;
    std::apply([labels, &txt](auto... targets) {
      int i = 0, label_left = 0;
      (([&](auto target) {
        const auto label_len = labels.find(',', label_left) - label_left;
        const auto label =
          std::regex_replace(labels.substr(label_left, label_len),
                             std::regex("^\\s+|\\s+$"), "");
        if (i >= 1) txt += ", ";
        txt += label + ": " + to_pretty_str(target);
        label_left += label_len + 1;
        i++;
      })(targets), ...);
      txt += ";";
    }, targets_tupl);
    return txt;
  }, line, file);
}
#  define dump(...) (dump_f((#__VA_ARGS__), std::make_tuple(__VA_ARGS__), (__LINE__), (__FILE__)), true)
void dump_canvas_f(std::string label, std::vector<std::string> canvas, int line = -1, std::string file = (__FILE__)) {
  debug_txt_f([=]() {
    int h = canvas.size(), w = canvas[0].size();
    std::string txt = label + " (" + std::to_string(h) + " x " + std::to_string(w) + ")\n";
    std::string ruler0(w, ' '), ruler1(w, '-');
    for (int x = 0; x < w; x += 4) {
      auto x_s = std::to_string(x);
      for (std::size_t i = 0; i < x_s.size(); i++) ruler0[x - i] = x_s[x_s.size() - i - 1];
      ruler1[x] = '+';
    }
    txt += "   |" + ruler0 + "\n---+" + ruler1;
    for (int y = 0; y < h; y++) {
      std::string ruler = "   |";
      if (y % 4 == 0) {
        auto y_s = std::to_string(y);
        for (std::size_t i = 0; i < y_s.size(); i++) ruler[2 - i] = y_s[y_s.size() - i - 1];
        ruler[3] = '+';
      }
      txt += "\n" + ruler + canvas[y];
    }
    return txt;
  }, line, file);
}
#  define dump_canvas(canvas) (dump_canvas_f((#canvas), (canvas), (__LINE__), (__FILE__)), true)
// TODO: dump_table
#else // DEBUG
#  pragma GCC diagnostic push
#    pragma GCC diagnostic ignored "-Wunused-value"
#    define debug_txt(...) (false)
#    define dump(...) (false)
#    define dump_canvas(...) (false)
#  pragma GCC diagnostic pop
#endif // DEBUG

/// main

#if !defined(__INCLUDE_LEVEL__) || __INCLUDE_LEVEL__ <= 1

inline std::string cp_main();

int main() {
  using namespace std;
  using namespace std::chrono;
#  ifdef DEBUG
  cerr << "[INFO] running in debug mode!" << endl;
  const auto start = system_clock::now();
  try {
#  endif // DEBUG
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(8);
    // run!!!
    const auto result = cp_main();
    if (!result.empty()) write_stdout(result);
#  ifdef DEBUG
    write_stdout('\n', true);
  } catch (exception &e) {
    write_stdout('\n', true);
    cerr << "[ERROR] " << e.what() << endl;
  }
  const auto end = system_clock::now();
  const auto time_ms = duration_cast<milliseconds>(end - start) - input_total_ms - debug_total_ms;
  cerr << "[INFO] finished in " << time_ms.count() << " ms!" << endl;
#  endif // DEBUG
  return 0;
}

#endif // __INCLUDE_LEVEL__

/// aliases

using i32 = int; using u32 = unsigned int;
using i64 = long long; using u64 = unsigned long long;
using i128 = __int128; using u128 = unsigned __int128;
using f32 = float; using f64 = double; using f128 = long double;
using str = std::string;
template <typename T> using vec = std::vector<T>;
template <typename T, typename Compare = std::less<T>> using p_que = std::priority_queue<T, std::vector<T>, Compare>;
template <typename Key, typename Compare = std::less<Key>> using mset = std::multiset<Key, Compare>;
template <typename Key, typename T, typename Compare = std::less<Key>> using mmap = std::multimap<Key, T, Compare>;
template <typename Key> using u_set = std::unordered_set<Key>;
template <typename Key> using u_mset = std::unordered_multiset<Key>;
template <typename Key, typename T> using u_map = std::unordered_map<Key, T>;
template <typename Key, typename T> using u_mmap = std::unordered_multimap<Key, T>;
#ifdef INCLUDED_BOOST_CPP_INT
using bigint = boost::multiprecision::cpp_int;
#endif // INCLUDED_BOOST_CPP_INT

using namespace std;
#if __cplusplus >= 202002L && __has_include(<ranges>)
namespace rng = std::ranges;
namespace viw = std::ranges::views;
#endif // C++20 && <ranges>
#ifdef INCLUDED_ACL
using namespace atcoder;
#endif // INCLUDED_ACL

#pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Wunused-variable"
constexpr auto infi = inf<int>();
constexpr auto infl = inf<long long>();
constexpr auto infd = inf<double>();
constexpr auto infld = inf<long double>();
const std::array YN = { "No"s, "Yes"s };
const std::array AB = { "Bob"s, "Alice"s };
const std::array FS = { "Second"s, "First"s };
const std::array TA = { "Aoki"s, "Takahashi"s };
#pragma GCC diagnostic pop

// functions
#define tostr to_string
#define dist distance
#define min_e min_element
#define max_e max_element
#define iota_v iota_view
#define p1 first
#define p2 second
#define has contains
#define eb emplace_back
#define ef emplace_front
#define pb pop_back
#define pf pop_front
// repeat
#define reps(i, l, r) for (std::decay_t<decltype(r)> i##_right = (r), i = (l); i < i##_right; i++)
#define rep(i, n) reps(i, 0, n)
#define rreps(i, l, r) for (std::decay_t<decltype(r)> i##_left = (l), i = (r) - 1; i >= i##_left; i--)
#define rrep(i, n) rreps(i, 0, n)
#define each(for_able) for (auto &&for_able##_i : (for_able))
// iterate
#define all(for_able) (std::begin(for_able)), (std::end(for_able))
#define rev(for_able) (std::rbegin(for_able)), (std::rend(for_able))
// lambda
#define pred(x, expr) ([&](auto &&x) -> bool { return (expr); })
#define comp(x, y, expr) ([&](auto &&x, auto &&y) -> bool { return (expr); })

/// answer

//using mint=modint998244353;

inline str cp_main() {
  int n=scan,m=scan,s=scan,t=scan;
  s--,t--;
  auto abcd=vector(m,pair(vec<int>(3),0LL));
  rep(i,m){
    input(abcd[i].p1[0]);
    input(abcd[i].p1[1]);
    input(abcd[i].p1[2]);
    input(abcd[i].p2);
  }
  vec<vec<pair<int,i64>>> g(n);
  for(auto &&[abc,d]:abcd){
    rep(i,3)abc[i]--;
    g[abc[0]].eb(abc[1],d);
    g[abc[0]].eb(abc[2],d);
    g[abc[1]].eb(abc[0],d);
    g[abc[1]].eb(abc[2],d);
    g[abc[2]].eb(abc[0],d);
    g[abc[2]].eb(abc[1],d);
  }
  vec<i64> cost(n,infl);
  p_que<pair<i64,int>,greater<>> q;
  q.emplace(cost[s]=0,s);
  while(!q.empty()){
    auto [cur_c,cur]=q.top();q.pop();
    if(cur_c>cost[cur])continue;
    for(auto [nxt,nxt_c]:g[cur]){
      if(chmin(cost[nxt],cur_c+nxt_c))q.emplace(cost[nxt],nxt);
    }
  }
  dump(cost);
  outputln(cost[t]);
  return "";
}
accuracy: 1
time_ms: 60
memory_kb: 31540
final_rank: 15

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

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int N,M,S,T;
  cin>>N>>M>>S>>T;
  --S,--T;
  vector G(N,vector(0,array<ll,2>()));
  for(int i=0;i<M;i++){
    int A,B,C,D;
    cin>>A>>B>>C>>D;
    --A,--B,--C;
    G[A].push_back({B,D});
    G[A].push_back({C,D});
    G[B].push_back({A,D});
    G[B].push_back({C,D});
    G[C].push_back({A,D});
    G[C].push_back({B,D});
  }
  priority_queue<array<ll,2>,vector<array<ll,2>>,greater<array<ll,2>>>pq;
  vector dist(N,1e18);
  dist[S]=0;
  pq.push({0,S});
  while(pq.size()){
    auto [d,v]=pq.top();
    pq.pop();
    if(d>dist[v])continue;
    for(auto [u,c]:G[v]){
      if(dist[u]>d+c){
        dist[u]=d+c;
        pq.push({d+c,u});
      }
    }
  }
  cout<<dist[T]<<'\n';
}
accuracy: 0.09090909090909091
time_ms: 10
memory_kb: 8332
final_rank: 20

code_snippet: // author: hotman78
// date: 2024/04/12-18:22:11

// --- begin raw code -----------------
// #include"cpplib/util/template.hpp"
// #include"cpplib/graph_tree/dijkstra.hpp"
// 
// void solve(){
//     lint n,m,s,t;
//     cin>>n>>m>>s>>t;
//     s--;t--;
//     graph_w<lint>g(n);
//     rep(i,m){
//         lint a,b,c,d;
//         cin>>a>>b>>c>>d;
//         a--;b--;c--;
//         g[a].emplace_back(b,d);
//         g[a].emplace_back(c,d);
//         g[b].emplace_back(a,d);
//         g[b].emplace_back(c,d);
//         g[c].emplace_back(a,d);
//         g[c].emplace_back(b,d);
//     }
//     cout<<dijkstra<lint>(g,s)[t]<<endl;
// }
// 
// int main(){
//     solve();
// }
// --- end raw code -----------------

#line 2 "cpplib/util/template.hpp"
#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx2")
#include <bits/stdc++.h>
using namespace std;
#line 1 "cpplib/util/ioutil.hpp"
// template <class Head,class... Args>
// std::ostream& output(std::ostream& out,const Head& head,const Args&... args){
//     out>>head;
//     return output(head,args...);
// }
// template <class Head>
// std::ostream& output(std::ostream& out,const Head& head){
//     out>>head;
//     return out;
// }

template <typename T, typename E>
std::ostream &operator<<(std::ostream &out, std::pair<T, E> v) {
    out << "(" << v.first << "," << v.second << ")";
    return out;
}

// template <class... Args>
// ostream& operator<<(ostream& out,std::tuple<Args...>v){
//     std::apply(output,v);
//     return out;
// }
#line 11 "cpplib/util/template.hpp"
struct __INIT__ {
    __INIT__() {
        cin.tie(0);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
    }
} __INIT__;
typedef long long lint;
constexpr long long INF = 1LL << 60;
constexpr int IINF = 1 << 30;
constexpr double EPS = 1e-10;
#ifndef REACTIVE
#define endl '\n';
#endif
typedef vector<lint> vec;
typedef vector<vector<lint>> mat;
typedef vector<vector<vector<lint>>> mat3;
typedef vector<string> svec;
typedef vector<vector<string>> smat;
template <typename T> using V = vector<T>;
template <typename T> using VV = V<V<T>>;
#define output(t)                                                              \
    {                                                                          \
        bool f = 0;                                                            \
        for (auto val : (t)) {                                                 \
            cout << (f ? " " : "") << val;                                     \
            f = 1;                                                             \
        }                                                                      \
        cout << endl;                                                          \
    }
#define output2(t)                                                             \
    {                                                                          \
        for (auto i : t)                                                       \
            output(i);                                                         \
    }
#define debug(t)                                                               \
    {                                                                          \
        bool f = 0;                                                            \
        for (auto i : t) {                                                     \
            cerr << (f ? " " : "") << i;                                       \
            f = 1;                                                             \
        }                                                                      \
        cerr << endl;                                                          \
    }
#define debug2(t)                                                              \
    {                                                                          \
        for (auto i : t)                                                       \
            debug(i);                                                          \
    }
#define loop(n) for (long long _ = 0; _ < (long long)(n); ++_)
#define _overload4(_1, _2, _3, _4, name, ...) name
#define __rep(i, a) repi(i, 0, a, 1)
#define _rep(i, a, b) repi(i, a, b, 1)
#define repi(i, a, b, c)                                                       \
    for (long long i = (long long)(a); i < (long long)(b); i += c)
#define rep(...) _overload4(__VA_ARGS__, repi, _rep, __rep)(__VA_ARGS__)
#define _overload3_rev(_1, _2, _3, name, ...) name
#define _rep_rev(i, a) repi_rev(i, 0, a)
#define repi_rev(i, a, b)                                                      \
    for (long long i = (long long)(b)-1; i >= (long long)(a); --i)
#define rrep(...) _overload3_rev(__VA_ARGS__, repi_rev, _rep_rev)(__VA_ARGS__)

#define all(n) begin(n), end(n)
template <typename T, typename E> bool chmin(T &s, const E &t) {
    bool res = s > t;
    s = min<T>(s, t);
    return res;
}
template <typename T, typename E> bool chmax(T &s, const E &t) {
    bool res = s < t;
    s = max<T>(s, t);
    return res;
}
const vector<lint> dx = {1, 0, -1, 0, 1, 1, -1, -1};
const vector<lint> dy = {0, 1, 0, -1, 1, -1, 1, -1};
#define SUM(v) accumulate(all(v), 0LL)
#if __cplusplus >= 201703L
template <typename T, typename... Args>
auto make_vector(T x, int arg, Args... args) {
    if constexpr (sizeof...(args) == 0)
        return vector<T>(arg, x);
    else
        return vector(arg, make_vector<T>(x, args...));
}
#endif
#define bit(n, a) ((n >> a) & 1)
#define extrep(v, ...) for (auto v : make_mat_impl({__VA_ARGS__}))
vector<vector<long long>> make_mat_impl(vector<long long> v) {
    if (v.empty())
        return vector<vector<long long>>(1, vector<long long>());
    long long n = v.back();
    v.pop_back();
    vector<vector<long long>> ret;
    vector<vector<long long>> tmp = make_mat_impl(v);
    for (auto e : tmp)
        for (long long i = 0; i < n; ++i) {
            ret.push_back(e);
            ret.back().push_back(i);
        }
    return ret;
}
using graph = vector<vector<int>>;
template <typename T> using graph_w = vector<vector<pair<int, T>>>;

#if __cplusplus >= 201703L
constexpr inline long long powll(long long a, long long b) {
    long long res = 1;
    while (b--)
        res *= a;
    return res;
}
#endif

template <typename T, typename E>
pair<T, E> &operator+=(pair<T, E> &s, const pair<T, E> &t) {
    s.first += t.first;
    s.second += t.second;
    return s;
}
template <typename T, typename E>
pair<T, E> &operator-=(pair<T, E> &s, const pair<T, E> &t) {
    s.first -= t.first;
    s.second -= t.second;
    return s;
}
template <typename T, typename E>
pair<T, E> operator+(const pair<T, E> &s, const pair<T, E> &t) {
    auto res = s;
    return res += t;
}
template <typename T, typename E>
pair<T, E> operator-(const pair<T, E> &s, const pair<T, E> &t) {
    auto res = s;
    return res -= t;
}
#define BEGIN_STACK_EXTEND(size)                                               \
    void *stack_extend_memory_ = malloc(size);                                 \
    void *stack_extend_origin_memory_;                                         \
    char *stack_extend_dummy_memory_ = (char *)alloca(                         \
        (1 + (int)(((long long)stack_extend_memory_) & 127)) * 16);            \
    *stack_extend_dummy_memory_ = 0;                                           \
    asm volatile("mov %%rsp, %%rbx\nmov %%rax, %%rsp"                          \
                 : "=b"(stack_extend_origin_memory_)                           \
                 : "a"((char *)stack_extend_memory_ + (size)-1024));
#define END_STACK_EXTEND                                                       \
    asm volatile("mov %%rax, %%rsp" ::"a"(stack_extend_origin_memory_));       \
    free(stack_extend_memory_);
int floor_pow(int n) { return n ? 31 - __builtin_clz(n) : 0; }
#line 5 "cpplib/graph_tree/graph_template.hpp"
/**
 * @brief グラフテンプレート
 */

using graph = std::vector<std::vector<int>>;
template <typename T>
using graph_w = std::vector<std::vector<std::pair<int, T>>>;

graph load_graph(int n, int m) {
    graph g(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        std::cin >> s >> t;
        --s;
        --t;
        g[s].push_back(t);
        g[t].push_back(s);
    }
    return g;
}
graph load_digraph(int n, int m) {
    graph g(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        std::cin >> s >> t;
        --s;
        --t;
        g[s].push_back(t);
    }
    return g;
}
graph load_graph0(int n, int m) {
    graph g(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        std::cin >> s >> t;
        g[s].push_back(t);
        g[t].push_back(s);
    }
    return g;
}
graph load_digraph0(int n, int m) {
    graph g(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        std::cin >> s >> t;
        g[s].push_back(t);
    }
    return g;
}
graph load_tree(int n) {
    graph g(n);
    for (int i = 0; i < n - 1; ++i) {
        int s, t;
        std::cin >> s >> t;
        --s;
        --t;
        g[s].push_back(t);
        g[t].push_back(s);
    }
    return g;
}
graph load_tree0(int n) {
    graph g(n);
    for (int i = 0; i < n - 1; ++i) {
        int s, t;
        std::cin >> s >> t;
        g[s].push_back(t);
        g[t].push_back(s);
    }
    return g;
}
graph load_treep(int n) {
    graph g(n);
    for (int i = 0; i < n - 1; ++i) {
        int t;
        std::cin >> t;
        g[i + 1].push_back(t);
        g[t].push_back(i + 1);
    }
    return g;
}
template <typename T> graph_w<T> load_graph_weight(int n, int m) {
    graph_w<T> g(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        T u;
        std::cin >> s >> t >> u;
        --s;
        --t;
        g[s].emplace_back(t, u);
        g[t].emplace_back(s, u);
    }
    return g;
}
template <typename T> graph_w<T> load_digraph_weight(int n, int m) {
    graph_w<T> g(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        T u;
        std::cin >> s >> t >> u;
        --s;
        --t;
        g[s].emplace_back(t, u);
    }
    return g;
}
template <typename T> graph_w<T> load_graph0_weight(int n, int m) {
    graph_w<T> g(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        T u;
        std::cin >> s >> t >> u;
        g[s].emplace_back(t, u);
        g[t].emplace_back(s, u);
    }
    return g;
}
template <typename T> graph_w<T> load_digraph0_weight(int n, int m) {
    graph_w<T> g(n);
    for (int i = 0; i < m; ++i) {
        int s, t;
        T u;
        std::cin >> s >> t >> u;
        g[s].emplace_back(t, u);
    }
    return g;
}
template <typename T> graph_w<T> load_tree_weight(int n) {
    graph_w<T> g(n);
    for (int i = 0; i < n - 1; ++i) {
        int s, t;
        T u;
        std::cin >> s >> t >> u;
        --s;
        --t;
        g[s].emplace_back(t, u);
        g[t].emplace_back(s, u);
    }
    return g;
}
template <typename T> graph_w<T> load_tree0_weight(int n) {
    graph_w<T> g(n);
    for (int i = 0; i < n - 1; ++i) {
        int s, t;
        T u;
        std::cin >> s >> t >> u;
        g[s].emplace_back(t, u);
        g[t].emplace_back(s, u);
    }
    return g;
}
template <typename T> graph_w<T> load_treep_weight(int n) {
    graph_w<T> g(n);
    for (int i = 0; i < n - 1; ++i) {
        int t;
        T u;
        std::cin >> t >> u;
        g[i + 1].emplace_back(t, u);
        g[t].emplace_back(i + 1, u);
    }
    return g;
}
#line 10 "cpplib/graph_tree/dijkstra.hpp"
/**
 * @brief ダイクストラ法 O((E+V)logE)
 */

template <typename T, typename F = std::less<T>, typename Add = std::plus<T>>
struct dijkstra {
    int s;
    std::vector<T> diff;
    std::vector<int> par;
    std::vector<int> used;
    dijkstra(const graph_w<T> &list, int s, T zero = T(),
             T inf = std::numeric_limits<T>::max(), F f = F(), Add add = Add())
        : s(s) {
        int n = list.size();
        diff.resize(n, inf);
        par.resize(n, -1);
        used.resize(n, 0);
        std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int>>,
                            std::greater<std::pair<T, int>>>
            que;
        diff[s] = zero;
        que.push(std::make_pair(T(), s));
        while (!que.empty()) {
            auto d = que.top();
            que.pop();
            T x;
            int now;
            std::tie(x, now) = d;
            if (used[now])
                continue;
            used[now] = 1;
            for (auto d2 : list[now]) {
                T sa;
                int to;
                std::tie(to, sa) = d2;
                T tmp = add(diff[now], sa);
                if (f(tmp, diff[to])) {
                    diff[to] = tmp;
                    par[to] = now;
                    que.emplace(diff[to], to);
                }
            }
        }
    }
    vector<T> get() { return diff; }
    T operator[](int idx) { return diff[idx]; }
    bool reachable(int t) { return par[t] != -1; }
    std::vector<int> get_path(int t) {
        std::vector<int> res;
        while (t != s) {
            res.push_back(t);
            t = par[t];
        }
        res.push_back(s);
        std::reverse(res.begin(), res.end());
        return res;
    }
};
#line 3 "main.cpp"

void solve() {
    lint n, m, s, t;
    cin >> n >> m >> s >> t;
    s--;
    t--;
    graph_w<lint> g(n);
    rep(i, m) {
        lint a, b, c, d;
        cin >> a >> b >> c >> d;
        a--;
        b--;
        c--;
        g[a].emplace_back(b, d);
        g[a].emplace_back(c, d);
        g[b].emplace_back(a, d);
        g[b].emplace_back(c, d);
        g[c].emplace_back(a, d);
        g[c].emplace_back(b, d);
    }
    cout << dijkstra<lint>(g, s)[t] << endl;
}

int main() { solve(); }
accuracy: 1
time_ms: 70
memory_kb: 25232
final_rank: 6

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

#define FOR(i, l, r) for(ll i = l; i < r; i++)
#define rep(i, n) FOR(i, 0, n)
#define FORR(i, l, r) for(ll i = r - 1; i >= l; i--)
#define ALL(ar) begin(ar), end(ar)

template <typename T1, typename T2>
inline bool chmax(T1 &a, T2 b) {
    return a < b && (a = b, true);
}
template <typename T1, typename T2>
inline bool chmin(T1 &a, T2 b) {
    return a > b && (a = b, true);
}
template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
    is >> p.first >> p.second;
    return is;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
    os << p.first << ' ' << p.second;
    return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
    for(T &x : v) is >> x;
    return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
    for(size_t i = 0; i < v.size(); i++) os << (i ? " " : "") << v[i];
    return os;
}
//-------------------------------------------------

void solve() {
    int n, m;
    cin >> n >> m;
    int s, t;
    cin >> s >> t;

    vector<ll> a(m), b(m), c(m), dd(m);

    struct edge {
        ll to1, to2;
        ll cost;
    };
    vector<vector<edge>> g(n);
    rep(i, m) {
        cin >> a[i] >> b[i] >> c[i] >> dd[i];
        a[i]--;
        b[i]--;
        c[i]--;

        g[a[i]].push_back(edge{b[i], c[i], dd[i]});
        g[b[i]].push_back(edge{c[i], a[i], dd[i]});
        g[c[i]].push_back(edge{a[i], b[i], dd[i]});
    }

    s--;
    t--;

    vector<ll> d(n, 1LL << 60);
    priority_queue<pair<ll, ll>> que;
    d[s] = 0;
    que.emplace(0, s);

    while(!que.empty()) {
        auto [dist, v] = que.top();
        que.pop();
        dist = -dist;
        if(dist > d[v]) continue;
        for(edge e : g[v]) {
            if(chmin(d[e.to1], dist + e.cost)) que.emplace(-d[e.to1], e.to1);
            if(chmin(d[e.to2], dist + e.cost)) que.emplace(-d[e.to2], e.to2);
        }
    }

    cout << d[t] << endl;
}

int main() {
    int t = 1;
    // cin >> t;
    while(t--) solve();
}
accuracy: 1
time_ms: 100
memory_kb: 23736
final_rank: 5

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

#define REP(i, n) for(ll i = 0;i < n;i++)
#define REPR(i, n) for(ll i = n;i >= 0;i--)
#define FOR(i, m, n) for(ll i = m;i < n;i++)
#define FORR(i, m, n) for(ll i = m;i >= n;i--)
#define REPO(i, n) for(ll i = 1;i <= n;i++)
#define ll long long
#define INF (ll)1ll << 60
#define MINF (-1 * INF)
#define ALL(n) n.begin(),n.end()
#define MOD (ll)1000000007
#define P pair<ll, ll>
ll d[210000]; // 結果
struct edge { ll to, cost; };
vector<edge> g[210000]; //隣接リスト to, cost
void dijkstra(ll a) { //だいくすとら！
	priority_queue<P, vector<P>, greater<P> > q;
	fill(d, d + 210000, INF);
	d[a] = 0;
	q.push(P(0, a));
	while (!q.empty()) {
		P p = q.top();
		q.pop();
		ll v = p.second;
		if (d[v] < p.first) continue;
		REP(i, g[v].size()) {
			edge e = g[v][i];
			if (d[e.to] > d[v] + e.cost) {
				d[e.to] = d[v] + e.cost;
				q.push(P(d[e.to], e.to));
			}
		}
	}
}
ll n, m, s, t;
map<ll, ll> mp;
int main(){
    cin >> n >> m >> s >> t;
    s--;
    t--;
    REP(i, m){
        ll a, b, c, d;
        cin >> a >> b >> c >> d;
        a--;
        b--;
        c--;
        g[a].push_back({b, d});
        g[a].push_back({c, d});
        g[b].push_back({a, d});
        g[b].push_back({c, d});
        g[c].push_back({b, d});
        g[c].push_back({a, d});
    }
    dijkstra(s);
    cout << d[t] << endl;
}
accuracy: 1
time_ms: 140
memory_kb: 27276
final_rank: 14

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

int main(){
  int n,m,s,t;
  cin >> n >> m >> s >> t;
  s--;
  t--;
  vector<vector<pair<int,ll>>> e(n,vector<pair<int,ll>>(0));
  for (int i=0;i<m;i++){
    int f,g,h,ff;
    cin >> f >> g >> h >> ff;
    f--;
    g--;
    h--;
    e[f].push_back({g,ff});
    e[f].push_back({h,ff});
    e[g].push_back({f,ff});
    e[g].push_back({h,ff});
    e[h].push_back({g,ff});
    e[h].push_back({f,ff});
  }
  vector<ll> d(n,1e18);
  d[s]=0;
  priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> q;
  q.push({0,s});
  while(!q.empty()){
    auto [f,g]=q.top();
    q.pop();
    if (d[g]!=f) continue;
    for (auto [ff,gg]:e[g]){
      if (d[ff]>d[g]+gg){
        d[ff]=d[g]+gg;
        q.push({d[ff],ff});
      }
    }
  }
  cout << d[t] << endl;
}
accuracy: 1
time_ms: 110
memory_kb: 26716
final_rank: 13

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

int main(){
    int n,m,s,t;
    cin>>n>>m>>s>>t;
    s--;t--;
    vector<int> a(m),b(m),c(m),d(m);
    vector<vector<int> > idx(n);
    vector<int> used(m,0);
    for(int i = 0;i<m;i++){
        cin>>a[i]>>b[i]>>c[i]>>d[i];
        a[i]--;b[i]--;c[i]--;
        idx[a[i]].push_back(i);
        idx[b[i]].push_back(i);
        idx[c[i]].push_back(i);
    }
    vector<vector<pair<ll,ll> > >e(n);
    vector<ll> dist(n,1e15);
    dist[s] = 0;
    using dat = pair<ll,int>;
    priority_queue<dat,vector<dat>,greater<dat> > que;
    que.push(make_pair(0LL,s));
    while(!que.empty()){
        ll now;int ni;
        tie(now,ni) = que.top();
        que.pop();
        if(dist[ni]<now) continue;
        for(auto i:idx[ni]) if(used[i]==0) {
            //cout<<ni<<" "<<i<<endl;
            used[i] = 1;
            if(a[i]==ni){
                e[ni].push_back(make_pair(d[i],b[i]));
                e[ni].push_back(make_pair(d[i],c[i]));
            }else if(b[i]==ni){
                e[ni].push_back(make_pair(d[i],a[i]));
                e[ni].push_back(make_pair(d[i],c[i]));
            }else{
                e[ni].push_back(make_pair(d[i],a[i]));
                e[ni].push_back(make_pair(d[i],b[i]));
            }
        }
        for(auto&to:e[ni]){
            ll nxt = to.first + now;
            if(nxt>=dist[to.second]) continue;
            dist[to.second] = nxt;
            que.push(make_pair(nxt,to.second));
        }
    }
    cout<<dist[t]<<endl;
}
accuracy: 1
time_ms: 110
memory_kb: 24096
final_rank: 7

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

int main(){
    int n, m, s, t, a, b, c, d, v, u;
    ll di;
    cin >> n >> m >> s >> t;
    s--, t--;
    vector<vector<pair<int,int>>> g(n);
    auto merge = [&](int u, int v, int w){
        g[u].emplace_back(v, w);
        g[v].emplace_back(u, w);
    };
    for(int i = 0; i < m; i++){
        cin >> a >> b >> c >> d;
        a--, b--, c--;
        merge(a, b, d);
        merge(b, c, d);
        merge(c, a, d);
    }
    priority_queue<pair<ll,int>,vector<pair<ll,int>>, greater<pair<ll,int>>> pq;
    vector<ll> dp(n, 1ll << 60);
    dp[s] = 0;
    pq.emplace(0, s);
    while(!pq.empty()){
        tie(di, v) = pq.top();
        pq.pop();
        if(di > dp[v])continue;
        for(auto &&pa:g[v]){
            tie(u, c) = pa;
            if(di + c >= dp[u])continue;
            dp[u] = di + c;
            pq.emplace(dp[u], u);
        }
    }
    cout << dp[t] << '\n';
}
accuracy: 1
time_ms: 100
memory_kb: 18240
final_rank: 2