제출 #535784

#제출 시각아이디문제언어결과실행 시간메모리
535784abc864197532Olympic Bus (JOI20_ho_t4)C++17
100 / 100
488 ms3964 KiB
#include <bits/stdc++.h>
using namespace std;
#define lli long long int
#define mp make_pair
#define eb emplace_back
#define pb push_back
#define pii pair<int,int>
#define X first
#define Y second
#define all(x) x.begin(), x.end()
void abc() {cout << endl;}
template <typename T, typename ...U> void abc(T i, U ...j) {
	cout << i << ' ', abc(j...);
}
template <typename T> void printv(T l, T r) {
	for (; l != r; ++l)
		cout << *l << " \n"[l + 1 == r];
}
#ifdef Doludu
#define test(x...) abc("[" + string(#x) + "]", x)
#define owo freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#else
#define test(x...) void(0)
#define owo ios::sync_with_stdio(false), cin.tie(0)
#endif
const int N = 205, M = 50001;

array <int, 4> E[M];

int dis1[2][2][N][N]; // dis[j][k] -> from s or t to k, forbid j
vector <int> adj[N][2];
int n, m;

void build1(int ty, int s, int forbid) {
	for (int t : {0, 1}) {
		vector <bool> vis(n, false);
		for (int i = 0; i < n; ++i) {
			dis1[ty][t][forbid][i] = 1 << 30;
		}
		dis1[ty][t][forbid][s] = 0;
		if (s == forbid)
			continue;
		while (true) {
			int v = -1;
			for (int i = 0; i < n; ++i) if (!vis[i]) {
				if (v == -1 || dis1[ty][t][forbid][v] > dis1[ty][t][forbid][i])
					v = i;
			}
			if (v == -1 || dis1[ty][t][forbid][v] == 1 << 30)
				break;
			vis[v] = true;
			for (int id : adj[v][t]) {
				int u = E[id][0] ^ E[id][1] ^ v;
				if (u == forbid)
					continue;
				if (dis1[ty][t][forbid][u] > dis1[ty][t][forbid][v] + E[id][2])
					dis1[ty][t][forbid][u] = dis1[ty][t][forbid][v] + E[id][2];
			}
		}
	}
}

int dis2[2][M]; // from s to t, avoid edge (i, j)

void build_special(int forbid, int s, int t, int ty) {
	// ignore edge (i, j), run shortest path
	vector <int> dis(n, 1 << 30);
	vector <bool> vis(n, false);
	dis[s] = 0;
	while (true) {
		int v = -1;
		for (int i = 0; i < n; ++i) if (!vis[i]) {
			if (v == -1 || dis[v] > dis[i])
				v = i;
		}
		if (v == -1 || dis[v] == 1 << 30)
			break;
		vis[v] = true;
		for (int id : adj[v][0]) if (id != forbid) {
			int u = E[id][0] ^ E[id][1] ^ v;
			if (dis[u] > dis[v] + E[id][2])
				dis[u] = dis[v] + E[id][2];
		}
	}
	dis2[ty][forbid] = dis[t];
}

lli ans = 0;

void build2(int s, int t, int ty) {
	vector <int> dis(n, 1 << 30);
	vector <bool> vis(n, false);
	vector <int> rt(n, -1);
	dis[s] = 0;
	while (true) {
		int v = -1;
		for (int i = 0; i < n; ++i) if (!vis[i]) {
			if (v == -1 || dis[v] > dis[i])
				v = i;
		}
		if (v == -1 || dis[v] == 1 << 30)
			break;
		vis[v] = true;
		for (int id : adj[v][0]) {
			int u = E[id][0] ^ E[id][1] ^ v;
			if (dis[u] > dis[v] + E[id][2])
				dis[u] = dis[v] + E[id][2], rt[u] = id;
		}
	}
	ans += dis[t];
	vector <bool> in_path(m, false);
	if (dis[t] != 1 << 30) {
		int now = t;
		while (now != s) {
			in_path[rt[now]] = true;
			now = E[rt[now]][0] ^ E[rt[now]][1] ^ now;
		}
	}
	for (int i = 0; i < m; ++i) {
		if (in_path[i])
			build_special(i, s, t, ty);
		else
			dis2[ty][i] = dis[t];
	}
}

int main () {
	owo;
	cin >> n >> m;
	int s = 0, t = n - 1;
	for (int i = 0, u, v, c, d; i < m; ++i) {
		cin >> u >> v >> c >> d, --u, --v;
		E[i] = {u, v, c, d};
		adj[u][0].pb(i);
		adj[v][1].pb(i);
	}
	for (int i = 0; i < n; ++i) {
		build1(0, s, i);
		build1(1, t, i);
	}
	build2(s, t, 0), build2(t, s, 1);
	for (int i = 0; i < m; ++i) {
		int u = E[i][0], v = E[i][1];
		lli rev = E[i][3];
		lli st = min((long long)dis1[0][0][u][v] + E[i][2] + dis1[1][1][v][u], 1ll * dis2[0][i]);
		lli ts = min((long long)dis1[1][0][u][v] + E[i][2] + dis1[0][1][v][u], 1ll * dis2[1][i]);
		ans = min(ans, rev + st + ts);
	}
	if (ans >= 1 << 30)
		ans = -1;
	cout << ans << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...