Problem:
MathJax.Hub.Config({ tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]} });

E: 敵襲から守れ

問題

島が $V$ 島あり、それぞれ $0, 1, ..., V-1$ と番号がついている。橋が $E$ 本あり、それぞれ $0, 1, ..., E-1$ と番号がついている。 $i$ 番目の橋は島 $s_i$ と島 $t_i$ にかかってあり、幅は $c_i$ である。

島 $0$ に基地があるAORイカちゃん軍団 (通称イカ団) は規模が弱小であるため、島 $V-1$ にあるSosu-Usa軍団 (通称そすうさ団) にいつもやられっぱなしである。ある日、イカ団は「そすうさ団が明日攻めてくる」との情報を得た。そすうさ団の基地から大人数のそすうさ団の部下が橋を渡って島を移動し、部下が一人でもイカ団の基地にたどり着かれるとイカ団は滅びてしまう……。

そこでイカ団は橋に通行止めテープを張ることで橋を通れないようにし、危機を免れようとした。使うテープの長さは通行止めにした橋の幅の総和である。また、そすうさ団の部下全員が必ずある一本の幅 $1$ の橋を通る場合、イカ団がそこで待ち伏せすることで、そすうさ団を通れなくすることができる。

保持しているテープの長さは $10^4$ である。今後のことも考え、消費するテープの量はなるべく少なくしたい。そすうさ団の部下がイカ団の基地にたどり着けないようにするために使うテープの長さの最小値を求めよ。ただし、テープの長さが足りずどうしても攻められてしまう合は
$-1$ を出力せよ。

制約

$2 \le V \le 5 \times 10^3$

$1 \le E \le min(5 \times 10^3, V(V-1)/2)$

$1 \le c_i \le 5 \times 10^3$

$0 \le s_i, t_i \lt V$

与えられるグラフは連結かつ単純である。

入力は全て整数で与えらえる。

入力形式

入力は以下の形式で与えられる。

$V \ E$
$s_0 \ t_0 \ c_0$
$s_1 \ t_1 \ c_1$
$\vdots$
$s_{E-1} \ t_{E-1} \ c_{E-1}$

出力

そすうさ団の部下がイカ団の基地にたどり着けないようにするために使うテープの長さの最小値を出力せよ。ただし、テープの長さが足りずどうしても攻められてしまう場合は $-1$ を出力せよ。また、末尾に改行も出力せよ。

サンプル

サンプル入力 1

4 4
0 1 3
0 2 4
1 3 1
2 3 5

サンプル出力 1

4

イカ団は $2$ 番目の橋で待ち伏せし、$1$ 番の橋にテープを貼ることで、そすうさ団を止められる。

サンプル入力 2

2 1
0 1 100

サンプル出力 2

100

$0$ 番目の橋にテープを貼ることで、そすうさ団を止められる。 橋の幅が $1$ でないため、待ち伏せはできない。

サンプル入力 3

5 6
0 1 5000
0 2 5000
0 3 5000
1 4 5000
2 4 5000
3 4 5000

サンプル出力 3

-1

テープが足りないため、どのようにテープを貼ってもそうすさ団は止められない。

Solution in C++14 (judge verdict: Time Limit Exceeded)

#include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = double;
const ld eps = 1e-9;
//
//using Graph = vector<vector<int>>;
//
//int dfs(const Graph&g, const int now, vector<int>&ch_cnts) {
//  ch_cnts[now]++;
//  for (auto&& e : g[now]) {
//      ch_cnts[now] += dfs(g, e, ch_cnts);
//  }
//  return ch_cnts[now];
//}
//
//struct HL_Edge {
//  int from;
//  int to;
//  bool heavy;
//};
//
//void dfs2(const Graph&g, vector<vector<HL_Edge>>&hl_tree, const int now, const vector<int>&ch_cnts) {
//
//  int max_ch_id = 1;
//  {
//      int max_ch_num = -1;
//      for (auto&&e : g[now]) {
//          if (max_ch_num < ch_cnts[e]) {
//              max_ch_num = ch_cnts[e];
//              max_ch_id = e;
//          }
//      }
//  }
//  for (auto e : g[now]) {
//      bool heavy = (e == max_ch_id);
//
//      hl_tree[now].push_back(HL_Edge{ now,e,heavy });
//  }
//  return;
//}
//
//void HL(const vector<vector<int>>&ro_tree) {
//  vector<int>ch_cnts(ro_tree.size());
//
//  dfs(ro_tree, 0, ch_cnts);
//
//  vector<vector<HL_Edge>>hl_tree(ro_tree.size());
//
//  dfs2(ro_tree, hl_tree, 0, ch_cnts);
//}
//
//namespace FastFourierTransform
//{
//  using C = complex< double >;
//
//  void DiscreteFourierTransform(vector< C > &F, bool rev)
//  {
//      const int N = (int)F.size();
//      const double PI = (rev ? -1 : 1) * acos(-1);
//      for (int i = 0, j = 1; j + 1 < N; j++) {
//          for (int k = N >> 1; k > (i ^= k); k >>= 1);
//          if (i > j) swap(F[i], F[j]);
//      }
//      C w, s, t;
//      for (int i = 1; i < N; i <<= 1) {
//          for (int k = 0; k < i; k++) {
//              w = polar(1.0, PI / i * k);
//              for (int j = 0; j < N; j += i * 2) {
//                  s = F[j + k];
//                  t = C(F[j + k + i].real() * w.real() - F[j + k + i].imag() * w.imag(),
//                      F[j + k + i].real() * w.imag() + F[j + k + i].imag() * w.real());
//                  F[j + k] = s + t, F[j + k + i] = s - t;
//              }
//          }
//      }
//      if (rev) for (int i = 0; i < N; i++) F[i] /= N;
//  }
//
//  vector< int> Multiply(const vector<int > &A, const vector<int > &B)
//  {
//      int sz = 1;
//      while (sz <= A.size() + B.size()) sz <<= 1;
//      vector< C > F(sz), G(sz);
//      for (int i = 0; i < A.size(); i++) F[i] = A[i];
//      for (int i = 0; i < B.size(); i++) G[i] = B[i];
//      DiscreteFourierTransform(F, false);
//      DiscreteFourierTransform(G, false);
//      for (int i = 0; i < sz; i++) F[i] *= G[i];
//      DiscreteFourierTransform(F, true);
//      vector< int > X(A.size() + B.size() - 1);
//      for (int i = 0; i < A.size() + B.size() - 1; i++) X[i] = F[i].real() + 0.5;
//      return (X);
//  }
//};



#define _GLIBCXX_DEBUG

using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()


//const int INF = 2147483647;
//const long long int L_INF = 9223372036854775807;

typedef long long int Weight;

const Weight INF = 1e18;
const Weight ZERO = 0;
struct Edge {
	int src, dst;
	Weight weight;
	Edge(int src, int dst, Weight weight) :
		src(src), dst(dst), weight(weight) { }
	Edge() :src(0), dst(0), weight(0) {

	}
};
bool operator < (const Edge &e, const Edge &f) {
	return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
	e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;
#define RESIDUE(s,t) (capacity[make_pair(s,t)]-flow[make_pair(s,t)])

//流量0の逆辺も張らないと正しく求まらないので注意
Weight maximumFlow(const Graph &ag, int s, int t) {

	Graph g(ag);
	for (int i = 0; i < ag.size(); ++i) {
		for (int j = 0; j < ag[i].size(); ++j) {
			int d = ag[i][j].dst;
			int s = ag[i][j].src;

			bool ok = false;
			for (int k = 0; k < ag[d].size(); ++k) {
				if (ag[d][k].src == s) {
					ok = true;
					break;
				}
			}
			if (!ok) {
				g[d].push_back(Edge(d, s, ZERO));
			}
		}
	}
	int n = g.size();
	//Matrix flow(n, Array(n,ZERO)), capacity(n, Array(n,ZERO));

	map<pair<int,int>,Weight>flow,capacity;
	REP(u, n) FOR(e, g[u]) capacity[make_pair(e->src,e->dst)] =capacity[make_pair(e->src, e->dst)]+ e->weight;


	Weight total = ZERO;
	while (1) {
		queue<int> Q; Q.push(s);
		vector<int> prev(n, -1); prev[s] = s;
		while (!Q.empty() && prev[t] < 0) {
			int u = Q.front(); Q.pop();
			FOR(e, g[u]) if (prev[e->dst] < 0 && RESIDUE(u, e->dst) > ZERO) {
				prev[e->dst] = u;
				Q.push(e->dst);
			}
		}
		if (prev[t] < 0)break; // prev[x] == -1 <=> t-side
		Weight inc = INF;
		for (int j = t; prev[j] != j; j = prev[j]){
			auto v(RESIDUE(prev[j], j));
			if (inc > v) {
				inc = v;
			}
		}
		for (int j = t; prev[j] != j; j = prev[j])
			flow[make_pair(prev[j],j)] =flow[make_pair(prev[j],j)]+inc, flow[make_pair(j,prev[j])] =flow[make_pair(j, prev[j])]- inc;;
		total += inc;
	}

	return total;
}


int main() {
	int V,E;cin>>V>>E;
	Graph g(V);
	for (int i = 0; i < E; ++i) {
		int f,t,c;cin>>f>>t>>c;
		long long int num=c*static_cast<long long int>(1e9);
		if(num==1e9)num--;
		g[f].push_back(Edge(f,t,num));
		g[t].push_back(Edge(t,f,num));

	}

	auto ans=maximumFlow(g,0,V-1);

	long long int nn=ans/(1e9);
	if(nn>1e4)nn=-1;
	cout<<nn<<endl;
	return 0;
}