Problem:
G - Revenge of Minimum Cost Flow
Problem Statement
Flora is a freelance carrier pigeon.
Since she is an excellent pigeon, there are too much task requests to her.
It is impossible to do all tasks, so she decided to outsource some tasks to Industrial Carrier Pigeon Company.
There are
N
cities numbered from 0 to
N-1
.
The task she wants to outsource is carrying
f
freight units from city
s
to city
t
.
There are
M
pigeons in the company.
The
i
-th pigeon carries freight from city
s_i
to
t_i
, and carrying cost of
u
units is
u a_i
if
u
is smaller than or equals to
d_i
, otherwise
d_i a_i + (u-d_i)b_i
.
Note that
i
-th pigeon cannot carry from city
t_i
to
s_i
.
Each pigeon can carry any amount of freights.
If the pigeon carried freight multiple times, the cost is calculated from total amount of freight units he/she carried.
Flora wants to minimize the total costs.
Please calculate minimum cost for her.
Input
The test case starts with a line containing five integers
N
(
2 \leq N \leq 100
),
M
(
1 \leq M \leq 1{,}000
),
s
(
0 \leq s \leq N-1
),
t
(
0 \leq t \leq N-1
) and
f
(
1 \leq f \leq 200
).
You may assume
s \neq t
.
Each of the next
M
lines contains five integers
s_i
(
0 \leq s_i \leq N-1
),
t_i
(
0 \leq t_i \leq N-1
),
a_i
(
0 \leq a_i \leq 1{,}000
),
b_i
(
0 \leq b_i \leq 1{,}000
) and
d_i
(
1 \leq d_i \leq 200
).
Each denotes
i
-th pigeon's information.
You may assume at most one pair of
a_i
and
b_i
satisfies
a_i < b_i
, all others satisfies
a_i > b_i
.
Output
Print the minimum cost to carry
f
freight units from city
s
to city
t
in a line.
If it is impossible to carry, print "Impossible" (quotes for clarity).
Sample Input 1
2 2 0 1 5
0 1 3 0 3
0 1 2 1 6
Output for the Sample Input 1
9
Sample Input 2
4 4 0 3 5
0 1 3 0 3
1 3 3 0 3
0 2 2 1 6
2 3 2 1 6
Output for the Sample Input 2
18
Sample Input 3
2 1 0 1 1
1 0 1 0 1
Output for the Sample Input 3
Impossible
Sample Input 4
2 2 0 1 2
0 1 5 1 2
0 1 6 3 1
Output for the Sample Input 4
9
Sample Input 5
3 3 0 2 4
0 2 3 4 2
0 1 4 1 3
1 2 3 1 1
Output for the Sample Input 5
14

Submitted solutions:

code_snippet: #pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;

template<typename T>
void chmin(T& a, T b) {
	a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
	a = max(a, b);
}
template<typename T>
void cinarray(vector<T>& v) {
	rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
	rep(i, v.size()) {
		if (i > 0)cout << " "; cout << v[i];
	}
	cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	if (x == 0)return 0;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	int n;
	modint() :n(0) { ; }
	modint(ll m) {
		if (m < 0 || mod <= m) {
			m %= mod; if (m < 0)m += mod;
		}
		n = m;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };

using mP = pair<modint, modint>;
//-----------------------------------

struct edge {
	int to, a, b, d;
};

int cost[201][100][100];
void solve() {
	int n, m, s, t, f; cin >> n >> m >> s >> t >> f;
	vector<vector<edge>> G(n);
	vector<edge> memo;
	vector<int> memofr;
	rep(i, m) {
		int x, y, a, b, d; cin >> x >> y >> a >> b >> d;
		if (a > b)G[x].push_back({ y,a,b,d });
		else {
			memo.push_back({ y,a,b,d });
			memofr.push_back(x);
		}
	}
	auto calccost = [&](edge e, int f) {
		if (f <= e.d)return e.a * f;
		else return e.a * e.d + (f - e.d) * e.b;
	};
	rep1(i, f) {
		rep(j, n) {
			rep(k, n)cost[i][j][k] = mod;
			cost[i][j][j] = 0;
			priority_queue<P, vector<P>, greater<P>> q;
			q.push({ 0,j });
			while (!q.empty()) {
				P p = q.top(); q.pop();
				int id = p.second;
				if (p.first > cost[i][j][id])continue;
				for (edge e : G[id]) {
					int nd = p.first + calccost(e, i);
					if (nd<cost[i][j][e.to]) {
						cost[i][j][e.to] = nd;
						q.push({ nd,e.to });
					}
				}
			}
		}
	}
	int ans = cost[f][s][t];
	if (memo.size()) {
		int x = memofr[0];
		int y = memo[0].to;
		for (int i = 1; i <= f; i++) {
			rep(j, n)rep(k, n) {
				ll val = (ll)cost[f][s][j] + cost[f - i][j][k] + cost[i][j][x] + calccost(memo[0], i) + cost[i][y][k] + cost[f][k][t];
				val = min(val, mod);
				ans = min(ans, (int)val);
			}
		}
	}
	if (ans == mod) {
		cout << "Impossible\n";
	}
	else {
		cout << ans << "\n";
	}
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	//init();
	//while(true)
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 19512
final_rank: 4

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


#define NUM 105

struct Edge{
	Edge(int arg_to,int arg_a,int arg_b,int arg_d){
		to = arg_to;
		a = arg_a;
		b = arg_b;
		d = arg_d;
		cost = BIG_NUM;
	}
	int to,a,b,d,cost;
};

struct State{
	State(int arg_node_id,int arg_sum_dist){

		node_id = arg_node_id;
		sum_dist = arg_sum_dist;

	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の降順(PQ)
	}

	int node_id,sum_dist;
};

int V,E;
int start,goal;
int FROM,TO;
int FLOW;
int min_dist[NUM];
int table_1[NUM][NUM],table_2[NUM][NUM],table_3[NUM][NUM];
vector<Edge> G[NUM];


void dijkstra(){

	//コストを計算する
	for(int i = 0; i < V; i++){
		for(int k = 0; k < G[i].size(); k++){

			if(FLOW <= G[i][k].d){

				G[i][k].cost = G[i][k].a*FLOW;

			}else{

				G[i][k].cost = (FLOW-G[i][k].d)*G[i][k].b+G[i][k].a*G[i][k].d;
			}
		}
	}

	for(int i = 0; i < V; i++){

		min_dist[i] = BIG_NUM;
	}

	min_dist[start] = 0;
	priority_queue<State> Q;

	Q.push(State(start,0));

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

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

				int next_node = G[Q.top().node_id][i].to;
				int next_cost = Q.top().sum_dist+G[Q.top().node_id][i].cost;

				if(min_dist[next_node] > next_cost){

					min_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}

			Q.pop();
		}
	}
}

void init(int table[NUM][NUM]){

	for(int i = 0; i < V; i++){
		for(int k = 0; k < V; k++){
			if(k != i){
				table[i][k] = BIG_NUM;
			}else{
				table[i][k] = 0;
			}
		}
	}
}

void calc_cost(int table[NUM][NUM],int base_flow,int table_index){

	for(int i = 0; i < V; i++){
		for(int k = 0; k < G[i].size(); k++){

			int cost;

			if(base_flow <= G[i][k].d){

				cost = G[i][k].a*base_flow;

			}else{

				cost = (base_flow-G[i][k].d)*G[i][k].b+G[i][k].a*G[i][k].d;
			}

			if(i == FROM && G[i][k].to == TO){

				if(table_index == 2){ //a < bとなっている辺には流さない

					if(G[i][k].a < G[i][k].b){

						cost = BIG_NUM;
					}

				}else if(table_index == 3){ //a < bとなっている辺に流す

					if(G[i][k].a > G[i][k].b){

						cost = BIG_NUM;
					}
				}

			}

			table[i][G[i][k].to] = min(table[i][G[i][k].to],cost);
		}
	}
}

void warshall_floyd(int table[NUM][NUM]){

	for(int mid = 0; mid < V; mid++){
		for(int L = 0; L < V; L++){
			if(table[L][mid] == BIG_NUM)continue;
			for(int R = 0; R < V; R++){
				if(table[mid][R] == BIG_NUM)continue;

				table[L][R] = min(table[L][R],table[L][mid]+table[mid][R]);
			}
		}
	}
}

int main(){

	scanf("%d %d %d %d %d",&V,&E,&start,&goal,&FLOW);

	bool FLG = false;

	int from,to,a,b,d;


	for(int loop = 0; loop < E; loop++){

		scanf("%d %d %d %d %d",&from,&to,&a,&b,&d);

		if(a < b){

			FLG = true;
			FROM = from;
			TO = to;
		}

		G[from].push_back(Edge(to,a,b,d));
	}

	dijkstra();

	if(!FLG){

		if(min_dist[goal] == BIG_NUM){

			printf("Impossible\n");

		}else{

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

		return 0;
	}

	//経路を分岐させる
	int ans = min_dist[goal];

	//FLOW流した場合のテーブル作成
	init(table_1);
	calc_cost(table_1,FLOW,1);
	warshall_floyd(table_1);

	for(int flow = 1; flow <= FLOW-1; flow++){ //流す配分を全通り試す:flow→a < bとなる辺に流す流量

		//FLOW-flow流した場合のテーブル作成
		init(table_2);
		calc_cost(table_2,FLOW-flow,2);
		warshall_floyd(table_2);


		//flow流した場合のテーブル作成
		init(table_3);
		calc_cost(table_3,flow,3);
		warshall_floyd(table_3);

		//分岐を全探索
		for(int mid_L = 0; mid_L < V; mid_L++){
			for(int mid_R = 0; mid_R < V; mid_R++){

				int cost_1 = table_1[start][mid_L];
				int cost_2 = table_2[mid_L][mid_R];
				int cost_3 = table_3[mid_L][mid_R];
				int cost_4 = table_1[mid_R][goal];

				if(cost_1 == BIG_NUM || cost_2 == BIG_NUM || cost_3 == BIG_NUM || cost_4 == BIG_NUM)continue;

				ans = min(ans,cost_1+cost_2+cost_3+cost_4);
			}
		}
	}

	if(ans == BIG_NUM){

		printf("Impossible\n");

	}else{

		printf("%d\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 3404
final_rank: 3

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


#define NUM 105

struct Edge{
	Edge(int arg_to,int arg_a,int arg_b,int arg_d){
		to = arg_to;
		a = arg_a;
		b = arg_b;
		d = arg_d;
		cost = BIG_NUM;
	}
	int to,a,b,d,cost;
};

struct State{
	State(int arg_node_id,int arg_sum_dist){

		node_id = arg_node_id;
		sum_dist = arg_sum_dist;

	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の降順(PQ)
	}

	int node_id,sum_dist;
};

int V,E;
int start,goal;
int FLOW;
int min_dist[NUM];
int table_1[NUM][NUM],table_2[NUM][NUM],table_3[NUM][NUM];
vector<Edge> G[NUM];


void dijkstra(){

	//コストを計算する
	for(int i = 0; i < V; i++){
		for(int k = 0; k < G[i].size(); k++){

			if(FLOW <= G[i][k].d){

				G[i][k].cost = G[i][k].a*FLOW;

			}else{

				G[i][k].cost = (FLOW-G[i][k].d)*G[i][k].b+G[i][k].a*G[i][k].d;
			}
		}
	}

	for(int i = 0; i < V; i++){

		min_dist[i] = BIG_NUM;
	}

	min_dist[start] = 0;
	priority_queue<State> Q;

	Q.push(State(start,0));

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

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

				int next_node = G[Q.top().node_id][i].to;
				int next_cost = Q.top().sum_dist+G[Q.top().node_id][i].cost;

				if(min_dist[next_node] > next_cost){

					min_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}

			Q.pop();
		}
	}
}

void init(int table[NUM][NUM]){

	for(int i = 0; i < V; i++){
		for(int k = 0; k < V; k++){
			if(k != i){
				table[i][k] = BIG_NUM;
			}else{
				table[i][k] = 0;
			}
		}
	}
}

void calc_cost(int table[NUM][NUM],int base_flow){

	for(int i = 0; i < V; i++){
		for(int k = 0; k < G[i].size(); k++){

			int cost;

			if(base_flow <= G[i][k].d){

				cost = G[i][k].a*base_flow;

			}else{

				cost = (base_flow-G[i][k].d)*G[i][k].b+G[i][k].a*G[i][k].d;
			}

			table[i][G[i][k].to] = cost;
		}
	}
}

void warshall_floyd(int table[NUM][NUM]){

	for(int mid = 0; mid < V; mid++){
		for(int L = 0; L < V; L++){
			if(table[L][mid] == BIG_NUM)continue;
			for(int R = 0; R < V; R++){
				if(table[mid][R] == BIG_NUM)continue;

				table[L][R] = min(table[L][R],table[L][mid]+table[mid][R]);
			}
		}
	}
}

int main(){

	scanf("%d %d %d %d %d",&V,&E,&start,&goal,&FLOW);

	bool FLG = false;

	int from,to,a,b,d;
	int FROM,TO;

	for(int loop = 0; loop < E; loop++){

		scanf("%d %d %d %d %d",&from,&to,&a,&b,&d);

		if(a < b){

			FLG = true;
			FROM = from;
			TO = to;
		}

		G[from].push_back(Edge(to,a,b,d));
	}

	dijkstra();

	if(!FLG){

		if(min_dist[goal] == BIG_NUM){

			printf("Impossible\n");

		}else{

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

		return 0;
	}

	//経路を分岐させる
	int ans = min_dist[goal];

	//FLOW流した場合のテーブル作成
	init(table_1);
	calc_cost(table_1,FLOW);
	warshall_floyd(table_1);

	for(int flow = 1; flow <= FLOW-1; flow++){ //流す配分を全通り試す:flow→a < bとなる辺に流す流量

		//FLOW-flow流した場合のテーブル作成
		init(table_2);
		calc_cost(table_2,FLOW-flow);
		table_2[FROM][TO] = BIG_NUM;//★★2重に流れないようにしておく★★
		warshall_floyd(table_2);


		//flow流した場合のテーブル作成
		init(table_3);
		calc_cost(table_3,flow);
		warshall_floyd(table_3);

		//分岐を全探索
		for(int mid_L = 0; mid_L < V; mid_L++){
			for(int mid_R = 0; mid_R < V; mid_R++){

				int cost_1 = table_1[start][mid_L];
				int cost_2 = table_2[mid_L][mid_R];
				int cost_3 = table_3[mid_L][mid_R];
				int cost_4 = table_1[mid_R][goal];

				if(cost_1 == BIG_NUM || cost_2 == BIG_NUM || cost_3 == BIG_NUM || cost_4 == BIG_NUM)continue;

				ans = min(ans,cost_1+cost_2+cost_3+cost_4);
			}
		}
	}

	if(ans == BIG_NUM){

		printf("Impossible\n");

	}else{

		printf("%d\n",ans);
	}

	return 0;
}
accuracy: 0.9852941176470589
time_ms: 300
memory_kb: 3388
final_rank: 6

code_snippet: #include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
struct edge{
	int t,a,b,d;
	edge(){}
	edge(int t,int a,int b,int d):t(t),a(a),b(b),d(d){}
};
vector<edge>g[120];
vector<edge>rev[120];
int w[120][120];
int ijk[120][5];
int v[120][5];
int main(){
	int n,m,s,t,f;
	scanf("%d%d%d%d%d",&n,&m,&s,&t,&f);
	int cnt=0;
	int p,q;
	int A,B,D;
	for(int i=0;i<m;i++){
		int a,b,c,d,e;
		scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
		g[a].push_back(edge(b,c,d,e));
		rev[b].push_back(edge(a,c,d,e));
		if(c<d){
			cnt++;
			p=a;
			q=b;
			A=c;B=d;D=e;
		}
	}
	for(int i=0;i<n;i++)for(int j=0;j<n;j++){
		if(i==j)w[i][j]=0;
		else w[i][j]=999999999;
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<g[i].size();j++){
			if(g[i][j].a<g[i][j].b)continue;
			w[i][g[i][j].t]=min(w[i][g[i][j].t],g[i][j].a*min(f,g[i][j].d)+g[i][j].b*max(0,f-g[i][j].d));
		}
	}
	for(int k=0;k<n;k++)for(int i=0;i<n;i++)for(int j=0;j<n;j++){
		w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
	}
	if(cnt==0){
		if(w[s][t]>888888888)printf("Impossible\n");
		else printf("%d\n",w[s][t]);
		return 0;
	}
	int ret=w[s][t];
	for(int i=1;i<=f;i++){
		int co=A*min(i,D)+B*max(0,i-D);
		for(int j=0;j<n;j++)for(int k=0;k<5;k++){
			v[j][k]=0;
			ijk[j][k]=999999999;
		}
		priority_queue<pair<int,pair<int,int> > >Q;
		ijk[p][3]=0;
		ijk[q][4]=0;
		Q.push(make_pair(0,make_pair(p,3)));
		Q.push(make_pair(0,make_pair(q,4)));
		while(Q.size()){
			int cost=-Q.top().first;
			int at=Q.top().second.first;
			int type=Q.top().second.second;
			Q.pop();
			if(v[at][type])continue;
			v[at][type]=1;
			if(type==3){
				for(int j=0;j<rev[at].size();j++){
					if(rev[at][j].a<rev[at][j].b)continue;
					int to=rev[at][j].t;
					int c1=rev[at][j].a*min(i,rev[at][j].d)+rev[at][j].b*max(0,i-rev[at][j].d);
					if(!v[to][type]&&ijk[to][type]>cost+c1){
						ijk[to][type]=cost+c1;
						Q.push(make_pair(-ijk[to][type],make_pair(to,type)));
					}
				}
			}else{
				for(int j=0;j<g[at].size();j++){
					if(g[at][j].a<g[at][j].b)continue;
					int to=g[at][j].t;
					int c1=g[at][j].a*min(i,g[at][j].d)+g[at][j].b*max(0,i-g[at][j].d);
					if(!v[to][type]&&ijk[to][type]>cost+c1){
						ijk[to][type]=cost+c1;
						Q.push(make_pair(-ijk[to][type],make_pair(to,type)));
					}
				}
			}
		}
		if(i==f&&ijk[s][3]<888888888&&ijk[t][4]<888888888){
			ret=min(ret,co+ijk[s][3]+ijk[t][4]);
		}
		ijk[s][0]=0;
		Q.push(make_pair(0,make_pair(s,0)));
		while(Q.size()){
			int cost=-Q.top().first;
			int at=Q.top().second.first;
			int type=Q.top().second.second;
			Q.pop();
			if(v[at][type])continue;
			v[at][type]=0;
			for(int j=0;j<g[at].size();j++){
				if(g[at][j].a<g[at][j].b)continue;
				int to=g[at][j].t;
				int c1=g[at][j].a*min(f,g[at][j].d)+g[at][j].b*max(0,f-g[at][j].d);
				int c2=g[at][j].a*min(f-i,g[at][j].d)+g[at][j].b*max(0,f-i-g[at][j].d);
				if(type==1)swap(c1,c2);
				if(!v[to][type]&&ijk[to][type]>cost+c1){
					ijk[to][type]=cost+c1;
					Q.push(make_pair(-ijk[to][type],make_pair(to,type)));
				}
			}
			int c3=ijk[at][3];
			if(type==1)c3=ijk[at][4];
			if(type<2&&!v[at][type+1]&&ijk[at][type+1]>cost+c3){
				ijk[at][type+1]=cost+c3;
				Q.push(make_pair(-ijk[at][type+1],make_pair(at,type+1)));
			}
		}
		//printf("%d: %d %d\n",i,ijk[t][2],co);
		ret=min(ret,ijk[t][2]+co);
	}
	if(ret>888888888)printf("Impossible\n");
	else printf("%d\n",ret);

}
accuracy: 1
time_ms: 20
memory_kb: 1156
final_rank: 2

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
const int oo=1073741819;
using namespace std;
struct point{
	int x,y,A,B,D;
}G[2005];
int f[205][105][105],g[105][105][3],b[105][105],d[205][105][105];
int n,m,s,t,F;
inline void Up(int &x,int y)
{
	if (x>y) x=y;
}
int main()
{
	scanf("%d%d%d%d%d",&n,&m,&s,&t,&F);
	s++,t++;
	int id=0;
	for (int i=1;i<=m;i++) {
		scanf("%d%d%d%d%d",&G[i].x,&G[i].y,&G[i].A,&G[i].B,&G[i].D);
		G[i].x++,G[i].y++;
		if (G[i].A<G[i].B) id=i;
	}
	for (int P=1;P<=F;P++) {
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++) 
				if (i!=j) f[P][i][j]=d[P][i][j]=oo;else f[P][i][j]=d[P][i][j]=0;
		for (int i=1;i<=m;i++) {
			if (G[i].A<G[i].B) continue;
			int x=G[i].x,y=G[i].y;
			if (P>G[i].D) Up(f[P][x][y],G[i].A*G[i].D+G[i].B*(P-G[i].D));
			else Up(f[P][x][y],P*G[i].A);
		}
		for (int k=1;k<=n;k++)
			for (int i=1;i<=n;i++)
				if (f[P][i][k]<oo)
					for (int j=1;j<=n;j++)
						if (f[P][k][j]<oo)
							Up(f[P][i][j],f[P][i][k]+f[P][k][j]);
	}
	if (id)
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
			for (int p=0;p<=F;p++) {
				int cos=0;
				if (p>G[id].D) cos=G[id].A*G[id].D+G[id].B*(p-G[id].D);
				else cos=G[id].A*p;
				if (f[F-p][i][j]<oo && f[p][i][G[id].x]<oo && f[p][G[id].y][j]<oo)
					Up(d[F][i][j],f[F-p][i][j]+f[p][i][G[id].x]+cos+f[p][G[id].y][j]);
			}
	int ans=min(f[F][s][t],d[F][s][t]);
	//cout<<f[F][s][s]<<endl;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
			if (f[F][s][i]<oo && d[F][i][j]<oo && f[F][j][t]<oo)
				Up(ans,f[F][s][i]+d[F][i][j]+f[F][j][t]);
	if (ans<oo) printf("%d\n",ans);
	else printf("Impossible\n");
	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 18828
final_rank: 5

code_snippet: #include <cstdio>
#include <vector>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const int INF=1<<28;
const int V_MAX=100;

struct edge{ int v,a,b,c; };

int main(){
	int n,m,s,t,F;
	while(~scanf("%d%d%d%d%d",&n,&m,&s,&t,&F) && n>0){
		vector<edge> G[V_MAX];
		rep(i,m){
			int u,v,a,b,c; scanf("%d%d%d%d%d",&u,&v,&a,&b,&c);
			G[u].push_back((edge){v,a,b,c});
		}

		edge z={-1}; // a<b の辺
		rep(u,n) rep(i,G[u].size()) {
			const edge &e=G[u][i];
			if(e.a<e.b) z=e;
		}

		static int d1[V_MAX][V_MAX]; // d1[u][v] := ( 流量 F の一本のフローを u -> v に流すための最小コスト )
		static int d2[V_MAX][V_MAX]; // 流量 z.c
		static int d3[V_MAX][V_MAX]; // 流量 F - z.c, ただし辺 z は通らない
		rep(u,n) rep(v,n) {
			d1[u][v]=(u==v?0:INF);
			d2[u][v]=(u==v?0:INF);
			d3[u][v]=(u==v?0:INF);
		}
		rep(u,n) rep(i,G[u].size()) {
			const edge &e=G[u][i];
			int v=e.v,a=e.a,b=e.b,c=e.c;
			if(F<=c) d1[u][v]=min(d1[u][v],a*F);
			else     d1[u][v]=min(d1[u][v],a*c+b*(F-c));
			if(z.v!=-1 && z.c<=F){
				if(z.c<=c) d2[u][v]=min(d2[u][v],a*z.c);
				else       d2[u][v]=min(d2[u][v],a*c+b*(z.c-c));
				if(a>=b){
					if((F-z.c)<=c) d3[u][v]=min(d3[u][v],a*(F-z.c));
					else           d3[u][v]=min(d3[u][v],a*c+b*((F-z.c)-c));
				}
			}
		}

		// Warshall-Floyd
		rep(w,n) rep(u,n) rep(v,n) d1[u][v]=min(d1[u][v],d1[u][w]+d1[w][v]);
		rep(w,n) rep(u,n) rep(v,n) d2[u][v]=min(d2[u][v],d2[u][w]+d2[w][v]);
		rep(w,n) rep(u,n) rep(v,n) d3[u][v]=min(d3[u][v],d3[u][w]+d3[w][v]);

		int ans=d1[s][t];
		rep(u,n) rep(v,n) ans=min(ans,d1[s][u]+d2[u][v]+d3[u][v]+d1[v][t]);

		if(ans<INF) printf("%d\n",ans); else puts("Impossible");
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1200
final_rank: 1