Problem:
H: Traditional Company
問題
あなたは Z 社の労働環境委員会の一員である。この役職たるもの、社員の出退勤時間や人間関係のモニタリングは欠かせないものだ。
Z 社には $N$ 人の社員がいる。それぞれの社員は $1$ から $N$ までの整数で番号付けられており、整数が小さいほど社員として新しいことを表す。社員が違えば仕事効率は十人十色だ。長時間の勤務もものともしない人もいれば、残業が嫌いな人や、そもそも仕事が苦手な人だっているのだ。具体的には、$i$ 番目の社員がすでに $t$ 単位時間働いているとき、単位時間 $\left[ t, t+1 \right)$ の間の仕事効率 $c_{i, t}$ は以下のように定められる。なお、$a_i \geq b_i$ が全ての $i$ について成立すると仮定してよい。
$c_{i, t} = \begin{cases} a_i & t < p_i \\ b_i & \text{otherwise} \end{cases}$
ここで、$i$ 番目の社員の出勤時間を $s_i$、退勤時間を $e_i$ とおこう ($s_i < e_i$)。$i$ 番目の社員の仕事量 $w_i$ は $w_i = \sum_{t=0}^{e_i-s_i-1} c_{i, t}$ と計算される。勤怠管理システムの都合上、それぞれの社員について出勤・退勤の単位時間 $s_i, e_i$ は
整数
でなければならないため、例えば $2.5$ 単位時間勤務したり、時刻 $3.5$ に出勤するなどは認められていない。また、勤務時間 $e_i - s_i$ は
$1$ 単位時間以上
必要なので注意しなければならない。
当然といえば当然なのだが、この社内には仲が良い者同士もいれば悪い者同士もいるし、そのどちらの関係でもない社員の組もある。仲が良い者同士なら一緒に仕事をする時間が欲しいものだが、仲が悪い者同士なら一緒に仕事をしたいとは思わないだろう。具体的には、社員 $i, j$ $(i \neq j)$ について仲が良い者同士である場合、$1$ 単位時間以上は必ず同時に仕事をしなければならない。また、社員 $i, j$ $(i \neq j)$ について仲が悪い者同士である場合、同時に仕事をする時間が $1$ 単位時間以上発生しないようにしなければならない。どちらでもない場合に関しては制限はない。例えば社員 $1$ の勤務時間が $[s_1, e_1) = [3, 5)$、社員 $2$ の勤務時間が $[s_2, e_2) = [5, 9)$ であるとき、同時に仕事をした時間が $1$ 単位時間未満であるため、この 2 人が仲が良い者同士である場合はこのような勤務時間帯は採用できない。仲が悪い者同士、あるいはどちらでもない場合はこのような勤務時間帯を採用することができる。
また、Z 社は伝統的精神を重んじているため、社員として新しいほど早めに出勤しなければならないルールが確立されている。具体的には、任意の社員の組 $i, j$ $(i < j)$ について、$s_i \leq s_j$ でなければならない。退勤時刻まで同様の制約をつけると長時間労働の原因となるため、退勤時刻に関しては制限はない。
さて、労働環境委員会の一員であるあなたの仕事は、会社全体の仕事量、つまり $\sum_{i} w_i$ を一定以上の水準に保ちつつオフィスの開放時間 $T$ をできるだけ短くすることである。オフィスの開放時間 $T$ は、$\max_{i} e_i - \min_{j} s_j$ で定義される。
入力形式
以下の形式で与えられる。
$N$ $M$ $X$
$a_1$ $b_1$ $p_1$
$a_2$ $b_2$ $p_2$
...
$a_N$ $b_N$ $p_N$
$u_1$ $v_1$ $f_1$
$u_2$ $v_2$ $f_2$
...
$u_M$ $v_M$ $f_M$
$1$ 行目の $N$ は Z 社の社員数を表し、$M$ は仲が良い、または仲が悪い人間関係の総数を表す。また、$X$ は会社全体の仕事量の下限を表す。つまり、会社全体の仕事量は $X$ 以上でなければならない。
$2$ 行目以降 $N$ 行はそれぞれの社員に関する情報を表す。$a_i, b_i$ は問題文中で説明されたように、$i$ 番目の社員の仕事効率に関する値を表し、$p_i$ は $i$ 番目の社員の仕事効率が切り替わる時間を表す。
$2+N$ 行目以降 $M$ 行は人間関係を表す。$u_i, v_i$ は、$i$ 番目の人間関係が社員 $u_i, v_i$ に関するものであることを表し、$f_i = 1$ であるときは「$u_i, v_i$ は仲が良い者同士である」ことを、$f_i = -1$ であるときは「$u_i, v_i$ は仲が悪い者同士である」ことを表す。なお、この $M$ 個の人間関係で明示されなかった社員の組に関しては、仲が良くも悪くもないと仮定してよい。
制約
入力はすべて整数で与えられる
$1 \leq N \leq 100$
$0 \leq M \leq 200$
$1 \leq X \leq 10^6$
$0 \leq |a_i|, |b_i| \leq 10^2$
$1 \leq p_i \leq 10^6$
$a_i \geq b_i$
$1 \leq u_i < v_i \leq N$
$(u_i, v_i) \neq (u_j, v_j)$ $(i \neq j)$
$f_i \in \left\{ -1, 1 \right\}$
出力形式
人間関係による制約を満たしつつ、会社全体の仕事量を $X$ 以上にできない場合、
-1
を出力せよ。そうでない場合、会社全体の仕事量を $X$ 以上にするときのオフィスの開放時間の最小値を出力せよ。
入力例 1
3 1 100
5 3 5
2 -1 9
2 1 5
1 2 -1
出力例 1
29
例えば以下のようにすれば達成可能である。
社員 $1$ が時刻 $0 $ で出勤、時刻 $20 $ で退勤 (仕事量 $5 \times 5 + 3 \times 15 = 70$)
社員 $2$ が時刻 $20 $ で出勤、時刻 $29 $ で退勤 (仕事量 $2 \times 9 = 18$)
社員 $3$ が時刻 $20 $ で出勤、時刻 $29$ で退勤 (仕事量 $2 \times 5 + 1 \times 4 = 14$)
社員 $1, 2$ は仲が悪い者同士であるが、同時に勤務している時間は $1$ 単位時間未満であるので条件を満たしており、また仕事量の合計は $70 + 18 + 14 = 102 (\geq 100)$ となっている。$29 $ よりも短い時間での達成は不可能であるため、これが答えとなる。$i < j$ ならば $s_i \leq s_j$ でなければならないことに注意せよ。
入力例 2
2 1 50
-3 -5 3
2 1 10
1 2 1
出力例 2
43
例えば以下のようにすれば達
...(truncated)

Submitted solutions:

code_snippet: //#define _GLIBCXX_DEBUG

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

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define UNIQUE(a) (a).erase(unique((a).begin(),(a).end()),(a).end())
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T> using PQ = priority_queue<T>;
template<typename T> using QP = priority_queue<T,vector<T>,greater<T>>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T1,typename T2,typename T3>void anss(T1 x,T2 y,T3 z){ans(x!=y,x,z);};  
template<typename T>void debug(const T &v,ll h,ll w,string sv=" "){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout<<sv<<v[i][j];cout<<endl;}};
template<typename T>void debug(const T &v,ll n,string sv=" "){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout<<sv<<v[i];cout<<endl;};
template<typename T>void debug(const vector<T>&v){debug(v,v.size());}
template<typename T>void debug(const vector<vector<T>>&v){for(auto &vv:v)debug(vv,vv.size());}
template<typename T>void debug(stack<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(queue<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(deque<T> st){while(!st.empty()){cout<<st.front()<<" ";st.pop_front();}cout<<endl;}
template<typename T>void debug(PQ<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(QP<T> st){while(!st.empty()){cout<<st.top()<<" ";st.pop();}cout<<endl;}
template<typename T>void debug(const set<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T>void debug(const multiset<T>&v){for(auto z:v)cout<<z<<" ";cout<<endl;}
template<typename T,size_t size>void debug(const array<T, size> &a){for(auto z:a)cout<<z<<" ";cout<<endl;}
template<typename T,typename V>void debug(const map<T,V>&v){for(auto z:v)cout<<"["<<z.first<<"]="<<z.second<<",";cout<<endl;}
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
template<typename T>void rearrange(vector<int>&ord, vector<T>&v){
  auto tmp = v;
  for(int i=0;i<tmp.size();i++)v[i] = tmp[ord[i]];
}
template<typename Head, typename... Tail>void rearrange(vector<int>&ord,Head&& head, Tail&&... tail){
  rearrange(ord, head);
  rearrange(ord, tail...);
}
template<typename T> vector<int> ascend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]<v[j];});
  return ord;
}
template<typename T> vector<int> descend(const vector<T>&v){
  vector<int>ord(v.size());iota(ord.begin(),ord.end(),0);
  sort(ord.begin(),ord.end(),[&](int i,int j){return v[i]>v[j];});
  return ord;
}
ll FLOOR(ll n,ll div){assert(div>0);return n>=0?n/div:(n-div+1)/div;}
ll CEIL(ll n,ll div){assert(div>0);return n>=0?(n+div-1)/div:n/div;}
ll digitsum(ll n){ll ret=0;while(n){ret+=n%10;n/=10;}return ret;}
ll modulo(ll n,ll d){return (n%d+d)%d;};
template<typename T>T min(const vector<T>&v){return *min_element(v.begin(),v.end());}
template<typename T>T max(const vector<T>&v){return *max_element(v.begin(),v.end());}
template<typename T>T acc(const vector<T>&v){return accumulate(v.begin(),v.end(),T(0));};
template<typename T>T reverse(const T &v){return T(v.rbegin(),v.rend());};
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
int popcount(ll x){return __builtin_popcountll(x);};
int poplow(ll x){return __builtin_ctzll(x);};
int pophigh(ll x){return 63 - __builtin_clzll(x);};
template<typename T>T poll(queue<T> &q){auto ret=q.front();q.pop();return ret;};
template<typename T>T poll(priority_queue<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(QP<T> &q){auto ret=q.top();q.pop();return ret;};
template<typename T>T poll(stack<T> &s){auto ret=s.top();s.pop();return ret;};
ll MULT(ll x,ll y){if(LLONG_MAX/x<=y)return LLONG_MAX;return x*y;}
ll POW2(ll x, ll k){ll ret=1,mul=x;while(k){if(mul==LLONG_MAX)return LLONG_MAX;if(k&1)ret=MULT(ret,mul);mul=MULT(mul,mul);k>>=1;}return ret;}
ll POW(ll x, ll k){ll ret=1;for(int i=0;i<k;i++){if(LLONG_MAX/x<=ret)return LLONG_MAX;ret*=x;}return ret;}
template< typename T = int >
struct edge {
  int to;
  T cost;
  int id;
  edge():id(-1){};
  edge(int to, T cost = 1, int id = -1):to(to), cost(cost), id(id){}
  operator int() const { return to; }
};

template<typename T>
using Graph = vector<vector<edge<T>>>;
template<typename T>
Graph<T>revgraph(const Graph<T> &g){
  Graph<T>ret(g.size());
  for(int i=0;i<g.size();i++){
    for(auto e:g[i]){
      int to = e.to;
      e.to = i;
      ret[to].push_back(e);
    }
  }
  return ret;
}
template<typename T>
Graph<T> readGraph(int n,int m,int indexed=1,bool directed=false,bool weighted=false){
  Graph<T> ret(n);
  for(int es = 0; es < m; es++){
    int u,v;
    T w=1;
    cin>>u>>v;u-=indexed,v-=indexed;
    if(weighted)cin>>w;
    ret[u].emplace_back(v,w,es);
    if(!directed)ret[v].emplace_back(u,w,es);
  }
  return ret;
}
template<typename T>
Graph<T> readParent(int n,int indexed=1,bool directed=true){
  Graph<T>ret(n);
  for(int i=1;i<n;i++){
    int p;cin>>p;
    p-=indexed;
    ret[p].emplace_back(i);
    if(!directed)ret[i].emplace_back(p);
  }
  return ret;
}
//https://github.com/beet-aizu/library/blob/master/bflow/capacityscaling.cpp

// O(m^2 \log m \log U)
// U: maximum capacity
enum Objective{
  MINIMIZE = +1,
  MAXIMIZE = -1,
};
template<typename Flow, typename Cost,
         Objective objective = Objective::MINIMIZE>
struct MinCostFlow{
  template<typename T> inline void chmin(T &x,T y){x=min(x,y);}

  struct Edge{
    int src,dst;
    Flow flow,cap;
    Cost cost;
    int rev;
    Edge(int src,int dst,Flow cap,Cost cost,int rev):
      src(src),dst(dst),flow(0),cap(cap),cost(cost),rev(rev){}
    Flow residual_cap()const{return cap-flow;}
  };

  struct EdgePtr{
    int v,e;
    EdgePtr(int v,int e):v(v),e(e){}
  };

  int n;
  vector<vector<Edge>> G;
  vector<Flow> b;
  vector<Cost> p;

  MinCostFlow(int n):n(n),G(n),b(n,0){}

  EdgePtr add_edge(int src,int dst,Flow lower,Flow upper,Cost cost){
    int e=G[src].size();
    int r=(src==dst?e+1:G[dst].size());
    assert(lower<=upper);
    G[src].emplace_back(src,dst,+upper,+cost*objective,r);
    G[dst].emplace_back(dst,src,-lower,-cost*objective,e);
    return EdgePtr(src,e);
  }

  const Edge &get_edge(EdgePtr ep)const{return G[ep.v][ep.e];}

  void push(Edge &e,Flow amount){
    e.flow+=amount;
    G[e.dst][e.rev].flow-=amount;
  }

  void add_supply(int v,Flow amount){b[v]+=amount;}
  void add_demand(int v,Flow amount){b[v]-=amount;}

  Cost residual_cost(const Edge &e){
    return e.cost+p[e.src]-p[e.dst];
  }

  vector<int> excess_vs,deficit_vs;
  void saturate_negative(const Flow delta){
    for(auto &es:G){
      for(auto &e:es){
        Flow cap=e.residual_cap();
        cap-=cap%delta;
        if(cap<0 or residual_cost(e)<0){
          push(e,cap);
          b[e.src]-=cap;
          b[e.dst]+=cap;
        }
      }
    }

    excess_vs.clear();
    deficit_vs.clear();
    for(int v=0;v<n;v++){
      if(b[v]>0) excess_vs.emplace_back(v);
      if(b[v]<0) deficit_vs.emplace_back(v);
    }
  }

  const Cost unreachable = std::numeric_limits<Cost>::max();
  Cost farthest;
  vector<Cost> dist;
  vector<Edge*> parent;

  struct P{
    Cost first;
    int second;
    P(Cost first,int second):first(first),second(second){}
    bool operator<(const P o)const{return first>o.first;}
  };

  priority_queue<P> pq;

  template<typename Predicate>
  void eliminate(vector<int> &vs,Predicate predicate){
    vs.erase(remove_if(begin(vs),end(vs),predicate),end(vs));
  }

  bool dual(const Flow delta){
    eliminate(excess_vs, [&](int v){return b[v]<+delta;});
    eliminate(deficit_vs,[&](int v){return b[v]>-delta;});

    dist.assign(n,unreachable);
    for(int v:excess_vs) pq.emplace(dist[v]=0,v);

    parent.assign(n,nullptr);
    auto emplace=[&](Edge& e){
      if(e.residual_cap()<delta) return;
      Cost nxt=dist[e.src]+residual_cost(e);
      if(nxt>=dist[e.dst]) return;
      pq.emplace(dist[e.dst]=nxt,e.dst);
      parent[e.dst]=&e;
    };

    farthest=0;
    int deficit_count=0;
    while(!pq.empty()){
      Cost d=pq.top().first;
      int v=pq.top().second;
      pq.pop();
      if(dist[v]<d) continue;
      farthest=d;

      if(b[v]<=-delta) deficit_count++;
      if(deficit_count>=(int)deficit_vs.size()) break;

      for(auto &e:G[v]) emplace(e);
    }
    pq=decltype(pq)();

    for(int v=0;v<n;v++)
      p[v]+=min(dist[v],farthest);

    return deficit_count>0;
  }

  void primal(const Flow delta){
    for(int t:deficit_vs){
      if(dist[t]>farthest) continue;
      Flow f=-b[t];
      int v;
      for(v=t;parent[v];v=parent[v]->src)
        chmin(f,parent[v]->residual_cap());
      chmin(f,b[v]);

      f-=f%delta;
      if(f<=0) continue;

      for(v=t;parent[v];){
        auto &e=*parent[v];
        push(e,f);
        int u=parent[v]->src;
        if(e.residual_cap()<=0) parent[v]=nullptr;
        v=u;
      }
      b[t]+=f;
      b[v]-=f;
    }
  }

  template<Flow SCALING_FACTOR=2>
  bool build(){
    p.resize(n);
    Flow max_flow=1;
    for(auto t:b) max_flow=max({max_flow,t,-t});
    for(auto &es:G)
      for(auto &e:es)
        max_flow=max({max_flow,e.residual_cap(),-e.residual_cap()});

    Flow delta=1;
    while(delta<max_flow) delta*=SCALING_FACTOR;
    for(;delta;delta/=SCALING_FACTOR){
      saturate_negative(delta);
      while(dual(delta)) primal(delta);
    }

    return excess_vs.empty() and deficit_vs.empty();
  }

  template<typename T=Cost>
  T get_cost(){
    T res=0;
    for(auto &es:G)
      for(auto &e:es)
        res+=T(e.flow)*T(e.cost)/T(objective);
    return res/T(2);
  }
  template<typename T=Cost> T get_gain(){return get_cost();}

  vector<Cost> get_potential(){
    fill(p.begin(),p.end(),0);
    for(int i=0;i<n;i++)
      for(auto &es:G)
        for(auto &e:es)
          if(e.residual_cap()>0)
            chmin(p[e.dst],p[e.src]+e.cost);
    return p;
  }
};

template<typename Flow, typename Cost>
using MaxGainFlow = MinCostFlow<Flow, Cost, Objective::MAXIMIZE>;
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
	ll n,m,x;cin>>n>>m>>x;
	vector<ll>a(n),b(n),p(n);
	rep(i,0,n){
		cin>>a[i]>>b[i]>>p[i];
	}
	vector<ll>u(m),v(m),f(m);
	rep(i,0,m)cin>>u[i]>>v[i]>>f[i],u[i]--,v[i]--;
	ll inf=1e15;
	ll tinf=1e7;
	ll ok=tinf,ng=0;
	while(ok-ng>=2){
		ll mid=(ok+ng)/2;
		MinCostFlow<ll,ll>mcf(2*n);
		rep(i,0,n){
			mcf.add_edge(0,i+n,0,inf,mid);
		}
		rep(i,0,n-1){
			mcf.add_edge(i+1,i,0,inf,0);
		}
		rep(i,0,m){
			if(f[i]==1)mcf.add_edge(u[i]+n,v[i],0,inf,-1);
			else{
				mcf.add_edge(v[i],u[i]+n,0,inf,0);
			}
		}
		rep(i,0,n){
			mcf.add_edge(i+n,i,0,inf,-1);
			mcf.add_edge(i+n,i,a[i],inf,0);
			mcf.add_edge(i,i+n,0,a[i]-b[i],p[i]);
		}
		bool sw=mcf.build();
		if(mcf.build()&&mcf.get_cost()>=x)ok=mid;
		else ng=mid;
		//debug(mcf.get_potential());
		//cout<<sw spa mid spa mcf.get_cost()<<endl;
	}
	//debug(u);
	//debug(v);
	//debug(f);
	anss(ok,tinf,-1);
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 3568
final_rank: 4

code_snippet: #line 1 "other/h.cpp"
#include <bits/extc++.h>
#if __has_include(<bit>)
#include <bit>
#endif
#line 7 "Library/alias.hpp"
namespace workspace {
constexpr char eol = '\n';
using namespace std;
using i32 = int_least32_t;
using i64 = int_least64_t;
using i128 = __int128_t;
using u32 = uint_least32_t;
using u64 = uint_least64_t;
using u128 = __uint128_t;
template <class T, class Comp = less<T>>
using priority_queue = std::priority_queue<T, vector<T>, Comp>;
template <class T> using stack = std::stack<T, vector<T>>;
}  // namespace workspace
#line 5 "Library/config.hpp"
namespace config {
const auto start_time{std::chrono::system_clock::now()};
int64_t elapsed() {
  using namespace std::chrono;
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - start_time).count();
}
__attribute__((constructor)) void setup() {
  using namespace std;
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(15);
#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (cin >> bufc)
      cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}
unsigned cases(), caseid = 1;
template <class F> void loop(F main) {
  for (const unsigned total = cases(); caseid <= total; ++caseid) main();
}
}  // namespace config
#line 2 "Library/option.hpp"
#ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #pragma GCC target("avx,avx2")
    #pragma GCC optimize("unroll-loops")
#endif
#line 2 "Library/utils/binary_search.hpp"
#if __cplusplus >= 201703L
#include <cassert>
#include <cmath>
#include <vector>
namespace workspace {
// binary search on a discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, iter_type>, bool>,
    iter_type>
binary_search(iter_type ok, iter_type ng, pred_type pred) {
  assert(ok != ng);
  std::make_signed_t<decltype(ng - ok)> dist(ng - ok);
  while (1 < dist || dist < -1) {
    iter_type mid(ok + dist / 2);
    if (pred(mid))
      ok = mid, dist -= dist / 2;
    else
      ng = mid, dist /= 2;
  }
  return ok;
}
// parallel binary search on each discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<iter_type>>,
                     std::vector<bool>>,
                 std::vector<iter_type>>
binary_search(std::vector<std::pair<iter_type, iter_type>> ends,
              pred_type pred) {
  std::vector<iter_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      iter_type mid(ok + (ng - ok) / 2);
      if (mids[i] != mid) {
        all_found = false;
        mids[i] = mid;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
// binary search on a real number interval.
template <class real_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, real_type>, bool>,
    real_type>
binary_search(real_type ok, real_type ng, const real_type eps, pred_type pred) {
  assert(ok != ng);
  while (ok + eps < ng || ng + eps < ok) {
    real_type mid{(ok + ng) / 2};
    (pred(mid) ? ok : ng) = mid;
  }
  return ok;
}
// parallel binary search on each real interval.
template <class real_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<real_type>>,
                     std::vector<bool>>,
                 std::vector<real_type>>
binary_search(std::vector<std::pair<real_type, real_type>> ends,
              const real_type eps, pred_type pred) {
  std::vector<real_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      if (ok + eps < ng || ng + eps < ok) {
        all_found = false;
        mids[i] = (ok + ng) / 2;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
}  // namespace workspace
#endif
#line 3 "Library/utils/casefmt.hpp"
namespace workspace {
std::ostream &casefmt(std::ostream& os) { return os << "Case #" << config::caseid << ": "; }
} // namespace workspace
#line 3 "Library/utils/chval.hpp"
namespace workspace {
template <class T, class Comp = std::less<T>>
bool chle(T &x, const T &y, Comp comp = Comp()) {
  return comp(y, x) ? x = y, true : false;
}
template <class T, class Comp = std::less<T>>
bool chge(T &x, const T &y, Comp comp = Comp()) {
  return comp(x, y) ? x = y, true : false;
}
}  // namespace workspace
#line 5 "Library/utils/coordinate_compression.hpp"

template <class T> class coordinate_compression {
  std::vector<T> uniquely;
  std::vector<size_t> compressed;

 public:
  coordinate_compression(const std::vector<T> &raw)
      : uniquely(raw), compressed(raw.size()) {
    std::sort(uniquely.begin(), uniquely.end());
    uniquely.erase(std::unique(uniquely.begin(), uniquely.end()),
                   uniquely.end());
    for (size_t i = 0; i != size(); ++i)
      compressed[i] =
          std::lower_bound(uniquely.begin(), uniquely.end(), raw[i]) -
          uniquely.begin();
  }

  size_t operator[](const size_t idx) const {
    assert(idx < size());
    return compressed[idx];
  }

  size_t size() const { return compressed.size(); }

  size_t count() const { return uniquely.size(); }

  T value(const size_t ord) const {
    assert(ord < count());
    return uniquely[ord];
  }

  size_t order(const T &value) const {
    return std::lower_bound(uniquely.begin(), uniquely.end(), value) -
           uniquely.begin();
  }

  auto begin() { return compressed.begin(); }
  auto end() { return compressed.end(); }
  auto rbegin() { return compressed.rbegin(); }
  auto rend() { return compressed.rend(); }
};
#line 3 "Library/utils/fixed_point.hpp"
namespace workspace {
// specify the return type of lambda.
template <class lambda_type> class fixed_point {
  lambda_type func;

 public:
  fixed_point(lambda_type &&f) : func(std::move(f)) {}
  template <class... Args> auto operator()(Args &&... args) const {
    return func(*this, std::forward<Args>(args)...);
  }
};
}  // namespace workspace
#line 6 "Library/utils/hash.hpp"

#line 3 "Library/utils/sfinae.hpp"
#include <type_traits>

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class T, class = int> struct mapped_of {
  using type = element_type<T>;
};
template <class T>
struct mapped_of<T,
                 typename std::pair<int, typename T::mapped_type>::first_type> {
  using type = typename T::mapped_type;
};
template <class T> using mapped_type = typename mapped_of<T>::type;

template <class T, class = void> struct is_integral_ext : std::false_type {};
template <class T>
struct is_integral_ext<
    T, typename std::enable_if<std::is_integral<T>::value>::type>
    : std::true_type {};
template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};
#if __cplusplus >= 201402
template <class T>
constexpr static bool is_integral_ext_v = is_integral_ext<T>::value;
#endif

template <typename T, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(2 < sizeof(T))>::type> {
  using type = uint_least64_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(4 < sizeof(T))>::type> {
  using type = __uint128_t;
};
#line 8 "Library/utils/hash.hpp"
namespace workspace {
template <class T, class = void> struct hash : std::hash<T> {};
#if __cplusplus >= 201703L
template <class Unique_bits_type>
struct hash<Unique_bits_type,
            enable_if_trait_type<Unique_bits_type,
                                 std::has_unique_object_representations>> {
  size_t operator()(uint64_t x) const {
    static const uint64_t m = std::random_device{}();
    x ^= x >> 23;
    x ^= m;
    x ^= x >> 47;
    return x - (x >> 32);
  }
};
#endif
template <class Key> size_t hash_combine(const size_t &seed, const Key &key) {
  return seed ^
         (hash<Key>()(key) + 0x9e3779b9 /* + (seed << 6) + (seed >> 2) */);
}
template <class T1, class T2> struct hash<std::pair<T1, T2>> {
  size_t operator()(const std::pair<T1, T2> &pair) const {
    return hash_combine(hash<T1>()(pair.first), pair.second);
  }
};
template <class... T> class hash<std::tuple<T...>> {
  template <class Tuple, size_t index = std::tuple_size<Tuple>::value - 1>
  struct tuple_hash {
    static uint64_t apply(const Tuple &t) {
      return hash_combine(tuple_hash<Tuple, index - 1>::apply(t),
                          std::get<index>(t));
    }
  };
  template <class Tuple> struct tuple_hash<Tuple, size_t(-1)> {
    static uint64_t apply(const Tuple &t) { return 0; }
  };

 public:
  uint64_t operator()(const std::tuple<T...> &t) const {
    return tuple_hash<std::tuple<T...>>::apply(t);
  }
};
template <class hash_table> struct hash_table_wrapper : hash_table {
  using key_type = typename hash_table::key_type;
  size_t count(const key_type &key) const {
    return hash_table::find(key) != hash_table::end();
  }
  template <class... Args> auto emplace(Args &&... args) {
    return hash_table::insert(typename hash_table::value_type(args...));
  }
};
template <class Key, class Mapped = __gnu_pbds::null_type>
using cc_hash_table =
    hash_table_wrapper<__gnu_pbds::cc_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped = __gnu_pbds::null_type>
using gp_hash_table =
    hash_table_wrapper<__gnu_pbds::gp_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped>
using unordered_map = std::unordered_map<Key, Mapped, hash<Key>>;
template <class Key> using unordered_set = std::unordered_set<Key, hash<Key>>;
}  // namespace workspace
#line 2 "Library/utils/make_vector.hpp"
#if __cplusplus >= 201703L
#include <vector>
namespace workspace {
template <typename T, size_t N>
constexpr auto make_vector(size_t* sizes, T const& init = T()) {
  if constexpr (N)
    return std::vector(*sizes, make_vector<T, N - 1>(std::next(sizes), init));
  else
    return init;
}
template <typename T, size_t N>
constexpr auto make_vector(const size_t (&sizes)[N], T const& init = T()) {
  return make_vector<T, N>((size_t*)sizes, init);
}
}  // namespace workspace
#endif
#line 3 "Library/utils/random_number_generator.hpp"
template <typename num_type> class random_number_generator {
  typename std::conditional<std::is_integral<num_type>::value,
                            std::uniform_int_distribution<num_type>,
                            std::uniform_real_distribution<num_type>>::type
      unif;

  std::mt19937 engine;

 public:
  random_number_generator(num_type min = std::numeric_limits<num_type>::min(),
                          num_type max = std::numeric_limits<num_type>::max())
      : unif(min, max), engine(std::random_device{}()) {}

  num_type min() const { return unif.min(); }

  num_type max() const { return unif.max(); }

  // generate a random number in [min(), max()].
  num_type operator()() { return unif(engine); }
};
#line 3 "Library/utils/read.hpp"
namespace workspace {
// read with std::cin.
template <class T = void>
struct read
{
    typename std::remove_const<T>::type value;
    template <class... types>
    read(types... args) : value(args...) { std::cin >> value; }
    operator T() const { return value; }
};
template <>
struct read<void>
{
    template <class T>
    operator T() const { T value; std::cin >> value; return value; }
};
} // namespace workspace
#line 4 "Library/utils/stream.hpp"

#line 6 "Library/utils/stream.hpp"
namespace std {
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ' ' << p.second;
}
template <class tuple_t, size_t index> struct tuple_is {
  static istream &apply(istream &is, tuple_t &t) {
    tuple_is<tuple_t, index - 1>::apply(is, t);
    return is >> get<index>(t);
  }
};
template <class tuple_t> struct tuple_is<tuple_t, SIZE_MAX> {
  static istream &apply(istream &is, tuple_t &t) { return is; }
};
template <class... T> istream &operator>>(istream &is, tuple<T...> &t) {
  return tuple_is<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is,
                                                                          t);
}
template <class tuple_t, size_t index> struct tuple_os {
  static ostream &apply(ostream &os, const tuple_t &t) {
    tuple_os<tuple_t, index - 1>::apply(os, t);
    return os << ' ' << get<index>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, 0> {
  static ostream &apply(ostream &os, const tuple_t &t) {
    return os << get<0>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, SIZE_MAX> {
  static ostream &apply(ostream &os, const tuple_t &t) { return os; }
};
template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) {
  return tuple_os<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os,
                                                                          t);
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   istream &>::type
operator>>(istream &is, Container &cont) {
  for (auto &&e : cont) is >> e;
  return is;
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   ostream &>::type
operator<<(ostream &os, const Container &cont) {
  bool head = true;
  for (auto &&e : cont) head ? head = 0 : (os << ' ', 0), os << e;
  return os;
}
}  // namespace std
#line 4 "Library/utils/trinary_search.hpp"
// trinary search on discrete range.
template <class iter_type, class comp_type>
iter_type trinary(iter_type first, iter_type last, comp_type comp)
{
    assert(first < last);
    intmax_t dist(last - first);
    while(dist > 2)
    {
        iter_type left(first + dist / 3), right(first + dist * 2 / 3);
        if(comp(left, right)) last = right, dist = dist * 2 / 3;
        else first = left, dist -= dist / 3;
    }
    if(dist > 1 && comp(first + 1, first)) ++first;
    return first;
}
// trinary search on real numbers.
template <class comp_type>
long double trinary(long double first, long double last, const long double eps, comp_type comp)
{
    assert(first < last);
    while(last - first > eps)
    {
        long double left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
        if(comp(left, right)) last = right;
        else first = left;
    }
    return first;
}
#line 2 "Library/utils/wrapper.hpp"
template <class Container> class reversed {
  Container &ref, copy;

 public:
  reversed(Container &ref) : ref(ref) {}
  reversed(Container &&ref = Container()) : ref(copy), copy(ref) {}
  auto begin() const { return ref.rbegin(); }
  auto end() const { return ref.rend(); }
};
#line 9 "other/h.cpp"

namespace workspace {
void main();
}
int main() { config::loop(workspace::main); }

unsigned config::cases() {
  // return -1; // unspecified
  // int t; std::cin >> t; return t; // given
  return 1;
}

#line 4 "Library/graph/directed/flow/min_cost_flow.hpp"

#line 4 "Library/graph/directed/flow/base.hpp"
// the base class of flow algorithms.
template <class cap_t, class cost_t> struct flow_base {
  struct edge_t {
    size_t src, dst;
    cap_t cap;
    cost_t cost;
    edge_t *rev;
    edge_t() = default;
    edge_t(size_t src, size_t dst, const cap_t &cap, edge_t *rev)
        : src(src), dst(dst), cap(cap), rev(rev) {}
    edge_t(size_t src, size_t dst, const cap_t &cap, const cost_t &cost,
           edge_t *rev)
        : src(src), dst(dst), cap(cap), cost(cost), rev(rev) {}
    const cap_t &flow(const cap_t &f = 0) { return cap -= f, rev->cap += f; }
    bool avbl() const { return static_cast<cap_t>(0) < cap; }
  };  // class edge_t

  class adj_type {
    edge_t *fst, *lst, *clst;

   public:
    template <class... Args> edge_t *emplace(Args &&... args) {
      if (lst == clst) {
        size_t len(clst - fst);
        edge_t *nfst = lst = new edge_t[len << 1];
        for (edge_t *p{fst}; p != clst; ++p, ++lst)
          p->rev->rev = lst, *lst = *p;
        delete[] fst;
        fst = nfst;
        clst = lst + len;
      }
      *lst = edge_t(args...);
      return lst++;
    }
    adj_type() : fst(new edge_t[1]), lst(fst), clst(fst + 1) {}
    ~adj_type() { delete[] fst; }
    edge_t &operator[](size_t i) {
      assert(i < size());
      return *(fst + i);
    }
    size_t size() const { return lst - fst; }
    edge_t *begin() const { return fst; }
    edge_t *end() const { return lst; }
  };  // class adj_type

  flow_base(size_t n = 0) : adjs(n) {}

  flow_base(const flow_base &other) : adjs(other.size()) {
    for (size_t node{}; node != size(); ++node)
      for (const auto &[src, dst, cap, cost, rev] : other[node])
        if (src == node) {
          edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
          ptr->rev = adjs[dst].emplace(dst, src, rev->cap, -cost, ptr);
          rev->src = nil;
        } else {
          rev->rev->src = node;
        }
  }

  flow_base &operator=(const flow_base &rhs) {
    if (this != &rhs) adjs.swap(flow_base(rhs).adjs);
    return *this;
  }

  size_t size() const { return adjs.size(); }

  adj_type &operator[](size_t node) {
    assert(node < size());
    return adjs[node];
  }
  const adj_type &operator[](size_t node) const {
    assert(node < size());
    return adjs[node];
  }

  virtual edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                           const cost_t &cost) {
    assert(src < size());
    assert(dst < size());
    assert(!(cap < static_cast<cap_t>(0)));
    if (!(static_cast<cap_t>(0) < cap) || src == dst) return nullptr;
    edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
    ptr->rev = adjs[dst].emplace(dst, src, 0, -cost, ptr);
    return ptr;
  }

 protected:
  constexpr static size_t nil = -1;
  std::vector<adj_type> adjs;
};  // class flow_base
#line 6 "Library/graph/directed/flow/min_cost_flow.hpp"
// Successive shortest paths algorithm.
template <class cap_t, class cost_t, bool density_tag = false>
class min_cost_flow : public flow_base<cap_t, cost_t> {
  using base = flow_base<cap_t, cost_t>;
  using edge_t = typename base::edge_t;
  using base::adjs;
  using base::nil;

  cost_t min_cost, total_cost;
  std::vector<cap_t> supp;
  std::vector<cost_t> ptnl;

  void copy_member(const min_cost_flow &other) {
    min_cost = other.min_cost;
    total_cost = other.total_cost;
    supp = other.supp;
    ptnl = other.ptnl;
  }

  void Dijkstra(std::vector<edge_t *> &last) {
    const cost_t infty(total_cost + 1);
    std::vector<cost_t> nptnl(size(), infty);
    if constexpr (density_tag) {
      // O(V^2)
      std::vector<bool> used(size());
      for (size_t src{}; src != size(); ++src) {
        if (static_cast<cap_t>(0) < supp[src]) {
          used[src] = true;
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (static_cast<cap_t>(0) < supp[e.dst]) continue;
            if (e.avbl() && e.cost < nptnl[e.dst]) {
              nptnl[e.dst] = e.cost;
              last[e.dst] = &e;
            }
          }
        }
      }
      for (;;) {
        size_t src{nil};
        cost_t sp{infty};
        for (size_t node{}; node != size(); ++node) {
          if (used[node] || nptnl[node] == infty) continue;
          cost_t dist{nptnl[node] - ptnl[node]};
          if (dist < sp) {
            sp = dist;
            src = node;
          }
        }
        if (src == nil) break;
        used[src] = true;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[src] + e.cost < nptnl[e.dst]) {
            nptnl[e.dst] = nptnl[src] + e.cost;
            last[e.dst] = &e;
          }
        }
      }
    } else {
      // O((V + E)logV)
      struct node_t {
        size_t id;
        cost_t dist;
        node_t(size_t id, cost_t dist) : id(id), dist(dist) {}
        bool operator<(const node_t &rhs) const { return rhs.dist < dist; }
      };
      std::priority_queue<node_t> que;
      for (size_t src{}; src != size(); ++src) {
        if (supp[src] > static_cast<cap_t>(0)) {
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (supp[e.dst] > static_cast<cap_t>(0)) continue;
            if (e.avbl() && nptnl[e.dst] > e.cost) {
              que.emplace(e.dst, (nptnl[e.dst] = e.cost) - ptnl[e.dst]);
              last[e.dst] = &e;
            }
          }
        }
      }
      while (!que.empty()) {
        auto [src, ndist] = que.top();
        que.pop();
        if (ndist + ptnl[src] != nptnl[src]) continue;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[e.dst] > nptnl[src] + e.cost) {
            que.emplace(e.dst,
                        (nptnl[e.dst] = nptnl[src] + e.cost) - ptnl[e.dst]);
            last[e.dst] = &e;
          }
        }
      }
    }
    ptnl.swap(nptnl);
  }

 public:
  using base::size;

  min_cost_flow(size_t n = 0)
      : base::flow_base(n), min_cost(0), total_cost(0), supp(n), ptnl(n) {}

  min_cost_flow(const min_cost_flow &other) : base::flow_base(other) {
    copy_member(other);
  }

  min_cost_flow &operator=(const min_cost_flow &other) {
    base::operator=(other);
    copy_member(other);
    return *this;
  }

  edge_t *add_edge(size_t src, size_t dst, const cost_t &cost);

  edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                   const cost_t &cost) override {
    assert(src != dst);
    if (cost < static_cast<cost_t>(0)) {
      supp[src] -= cap;
      supp[dst] += cap;
      min_cost += cap * cost;
      total_cost -= cap * cost;
      return base::add_edge(dst, src, cap, -cost);
    }
    total_cost += cap * cost;
    return base::add_edge(src, dst, cap, cost);
  }

  edge_t *add_edge(size_t src, size_t dst, const cap_t &lower,
                   const cap_t &upper, const cost_t &cost) {
    assert(!(upper < lower));
    supp[src] -= lower;
    supp[dst] += lower;
    min_cost += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  const cap_t &supply(size_t node, const cap_t &vol = 0) {
    assert(node < size());
    return supp[node] += vol;
  }

  const cap_t &demand(size_t node, const cap_t &vol) {
    return supply(node, -vol);
  }

  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge_t *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_t dst{}; dst != size(); ++dst) {
        if (supp[dst] < static_cast<cap_t>(0) and last[dst]) {
          cap_t resid{-supp[dst]};
          size_t src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < supp[src])) {
              resid = supp[src];
              block = src;
            }
            for (edge_t *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            supp[src] -= resid;
            supp[dst] += resid;
            min_cost += ptnl[dst] * resid;
            aug = true;
          }
          if (~block) {
            for (size_t node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
          }
        }
      }
    }
    return std::none_of(begin(supp), end(supp),
                        [](const cap_t &s) { return s < 0 || 0 < s; });
  }

  cost_t optimal() {
    assert(flow());
    return min_cost;
  }
};  // class min_cost_flow
#line 22 "other/h.cpp"

namespace workspace {
void main() {
  // start here!
  const i64 inf = 1e10;
  int n, m, x;
  cin >> n >> m >> x;

  min_cost_flow<i64, i64> base(n * 3);
  // make
  {
    for (int i = 0; i < n; i++) {
      int a, b, p;
      cin >> a >> b >> p;
      base.add_edge(3 * i + 1, 3 * i, inf, p);
      base.add_edge(3 * i, 3 * i + 1, inf, -1);
      base.add_edge(3 * i + 1, 3 * i + 2, inf, 0);
      if (i) base.add_edge(3 * (i - 1), 3 * i, inf, 0);
      base.supply(3 * i, -a);
      base.supply(3 * i + 1, a - b);
      base.supply(3 * i + 2, b);
    }
  }
  for (auto j = 0; j < m; ++j) {
    int u, v, f;
    cin >> u >> v >> f;
    --u, --v;
    if (f > 0) {
      base.add_edge(3 * v, 3 * u + 2, inf, 1);
    } else {
      base.add_edge(3 * u + 2, 3 * v, inf, 0);
    }
  }

  auto ok = [&](int t) -> bool {
    auto mcf = base;
    for (int i = 0; i < n; i++) {
      mcf.add_edge(3 * i + 2, 0, inf, t);
    }
    if (mcf.flow()) {
      auto opt = mcf.optimal();
      return opt >= x;
    }
    return false;
  };
  
  const int tmax = x + 100 * n * (n - 1); 

  auto ans = binary_search(tmax + 1, -1, ok);
  if (ans > tmax)
    cout << "-1\n";
  else
    cout << ans << eol;
}
}
accuracy: 0.4222222222222222
time_ms: 40
memory_kb: 3600
final_rank: 14

code_snippet: #line 1 "other/h.cpp"
#include <bits/extc++.h>
#if __has_include(<bit>)
#include <bit>
#endif
#line 7 "Library/alias.hpp"
namespace workspace {
constexpr char eol = '\n';
using namespace std;
using i32 = int_least32_t;
using i64 = int_least64_t;
using i128 = __int128_t;
using u32 = uint_least32_t;
using u64 = uint_least64_t;
using u128 = __uint128_t;
template <class T, class Comp = less<T>>
using priority_queue = std::priority_queue<T, vector<T>, Comp>;
template <class T> using stack = std::stack<T, vector<T>>;
}  // namespace workspace
#line 5 "Library/config.hpp"
namespace config {
const auto start_time{std::chrono::system_clock::now()};
int64_t elapsed() {
  using namespace std::chrono;
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - start_time).count();
}
__attribute__((constructor)) void setup() {
  using namespace std;
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(15);
#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (cin >> bufc)
      cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}
unsigned cases(), caseid = 1;
template <class F> void loop(F main) {
  for (const unsigned total = cases(); caseid <= total; ++caseid) main();
}
}  // namespace config
#line 2 "Library/option.hpp"
#ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #pragma GCC target("avx,avx2")
    #pragma GCC optimize("unroll-loops")
#endif
#line 2 "Library/utils/binary_search.hpp"
#if __cplusplus >= 201703L
#include <cassert>
#include <cmath>
#include <vector>
namespace workspace {
// binary search on a discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, iter_type>, bool>,
    iter_type>
binary_search(iter_type ok, iter_type ng, pred_type pred) {
  assert(ok != ng);
  std::make_signed_t<decltype(ng - ok)> dist(ng - ok);
  while (1 < dist || dist < -1) {
    iter_type mid(ok + dist / 2);
    if (pred(mid))
      ok = mid, dist -= dist / 2;
    else
      ng = mid, dist /= 2;
  }
  return ok;
}
// parallel binary search on each discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<iter_type>>,
                     std::vector<bool>>,
                 std::vector<iter_type>>
binary_search(std::vector<std::pair<iter_type, iter_type>> ends,
              pred_type pred) {
  std::vector<iter_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      iter_type mid(ok + (ng - ok) / 2);
      if (mids[i] != mid) {
        all_found = false;
        mids[i] = mid;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
// binary search on a real number interval.
template <class real_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, real_type>, bool>,
    real_type>
binary_search(real_type ok, real_type ng, const real_type eps, pred_type pred) {
  assert(ok != ng);
  while (ok + eps < ng || ng + eps < ok) {
    real_type mid{(ok + ng) / 2};
    (pred(mid) ? ok : ng) = mid;
  }
  return ok;
}
// parallel binary search on each real interval.
template <class real_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<real_type>>,
                     std::vector<bool>>,
                 std::vector<real_type>>
binary_search(std::vector<std::pair<real_type, real_type>> ends,
              const real_type eps, pred_type pred) {
  std::vector<real_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      if (ok + eps < ng || ng + eps < ok) {
        all_found = false;
        mids[i] = (ok + ng) / 2;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
}  // namespace workspace
#endif
#line 3 "Library/utils/casefmt.hpp"
namespace workspace {
std::ostream &casefmt(std::ostream& os) { return os << "Case #" << config::caseid << ": "; }
} // namespace workspace
#line 3 "Library/utils/chval.hpp"
namespace workspace {
template <class T, class Comp = std::less<T>>
bool chle(T &x, const T &y, Comp comp = Comp()) {
  return comp(y, x) ? x = y, true : false;
}
template <class T, class Comp = std::less<T>>
bool chge(T &x, const T &y, Comp comp = Comp()) {
  return comp(x, y) ? x = y, true : false;
}
}  // namespace workspace
#line 5 "Library/utils/coordinate_compression.hpp"

template <class T> class coordinate_compression {
  std::vector<T> uniquely;
  std::vector<size_t> compressed;

 public:
  coordinate_compression(const std::vector<T> &raw)
      : uniquely(raw), compressed(raw.size()) {
    std::sort(uniquely.begin(), uniquely.end());
    uniquely.erase(std::unique(uniquely.begin(), uniquely.end()),
                   uniquely.end());
    for (size_t i = 0; i != size(); ++i)
      compressed[i] =
          std::lower_bound(uniquely.begin(), uniquely.end(), raw[i]) -
          uniquely.begin();
  }

  size_t operator[](const size_t idx) const {
    assert(idx < size());
    return compressed[idx];
  }

  size_t size() const { return compressed.size(); }

  size_t count() const { return uniquely.size(); }

  T value(const size_t ord) const {
    assert(ord < count());
    return uniquely[ord];
  }

  size_t order(const T &value) const {
    return std::lower_bound(uniquely.begin(), uniquely.end(), value) -
           uniquely.begin();
  }

  auto begin() { return compressed.begin(); }
  auto end() { return compressed.end(); }
  auto rbegin() { return compressed.rbegin(); }
  auto rend() { return compressed.rend(); }
};
#line 3 "Library/utils/fixed_point.hpp"
namespace workspace {
// specify the return type of lambda.
template <class lambda_type> class fixed_point {
  lambda_type func;

 public:
  fixed_point(lambda_type &&f) : func(std::move(f)) {}
  template <class... Args> auto operator()(Args &&... args) const {
    return func(*this, std::forward<Args>(args)...);
  }
};
}  // namespace workspace
#line 6 "Library/utils/hash.hpp"

#line 3 "Library/utils/sfinae.hpp"
#include <type_traits>

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class T, class = int> struct mapped_of {
  using type = element_type<T>;
};
template <class T>
struct mapped_of<T,
                 typename std::pair<int, typename T::mapped_type>::first_type> {
  using type = typename T::mapped_type;
};
template <class T> using mapped_type = typename mapped_of<T>::type;

template <class T, class = void> struct is_integral_ext : std::false_type {};
template <class T>
struct is_integral_ext<
    T, typename std::enable_if<std::is_integral<T>::value>::type>
    : std::true_type {};
template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};
#if __cplusplus >= 201402
template <class T>
constexpr static bool is_integral_ext_v = is_integral_ext<T>::value;
#endif

template <typename T, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(2 < sizeof(T))>::type> {
  using type = uint_least64_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(4 < sizeof(T))>::type> {
  using type = __uint128_t;
};
#line 8 "Library/utils/hash.hpp"
namespace workspace {
template <class T, class = void> struct hash : std::hash<T> {};
#if __cplusplus >= 201703L
template <class Unique_bits_type>
struct hash<Unique_bits_type,
            enable_if_trait_type<Unique_bits_type,
                                 std::has_unique_object_representations>> {
  size_t operator()(uint64_t x) const {
    static const uint64_t m = std::random_device{}();
    x ^= x >> 23;
    x ^= m;
    x ^= x >> 47;
    return x - (x >> 32);
  }
};
#endif
template <class Key> size_t hash_combine(const size_t &seed, const Key &key) {
  return seed ^
         (hash<Key>()(key) + 0x9e3779b9 /* + (seed << 6) + (seed >> 2) */);
}
template <class T1, class T2> struct hash<std::pair<T1, T2>> {
  size_t operator()(const std::pair<T1, T2> &pair) const {
    return hash_combine(hash<T1>()(pair.first), pair.second);
  }
};
template <class... T> class hash<std::tuple<T...>> {
  template <class Tuple, size_t index = std::tuple_size<Tuple>::value - 1>
  struct tuple_hash {
    static uint64_t apply(const Tuple &t) {
      return hash_combine(tuple_hash<Tuple, index - 1>::apply(t),
                          std::get<index>(t));
    }
  };
  template <class Tuple> struct tuple_hash<Tuple, size_t(-1)> {
    static uint64_t apply(const Tuple &t) { return 0; }
  };

 public:
  uint64_t operator()(const std::tuple<T...> &t) const {
    return tuple_hash<std::tuple<T...>>::apply(t);
  }
};
template <class hash_table> struct hash_table_wrapper : hash_table {
  using key_type = typename hash_table::key_type;
  size_t count(const key_type &key) const {
    return hash_table::find(key) != hash_table::end();
  }
  template <class... Args> auto emplace(Args &&... args) {
    return hash_table::insert(typename hash_table::value_type(args...));
  }
};
template <class Key, class Mapped = __gnu_pbds::null_type>
using cc_hash_table =
    hash_table_wrapper<__gnu_pbds::cc_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped = __gnu_pbds::null_type>
using gp_hash_table =
    hash_table_wrapper<__gnu_pbds::gp_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped>
using unordered_map = std::unordered_map<Key, Mapped, hash<Key>>;
template <class Key> using unordered_set = std::unordered_set<Key, hash<Key>>;
}  // namespace workspace
#line 2 "Library/utils/make_vector.hpp"
#if __cplusplus >= 201703L
#include <vector>
namespace workspace {
template <typename T, size_t N>
constexpr auto make_vector(size_t* sizes, T const& init = T()) {
  if constexpr (N)
    return std::vector(*sizes, make_vector<T, N - 1>(std::next(sizes), init));
  else
    return init;
}
template <typename T, size_t N>
constexpr auto make_vector(const size_t (&sizes)[N], T const& init = T()) {
  return make_vector<T, N>((size_t*)sizes, init);
}
}  // namespace workspace
#endif
#line 3 "Library/utils/random_number_generator.hpp"
template <typename num_type> class random_number_generator {
  typename std::conditional<std::is_integral<num_type>::value,
                            std::uniform_int_distribution<num_type>,
                            std::uniform_real_distribution<num_type>>::type
      unif;

  std::mt19937 engine;

 public:
  random_number_generator(num_type min = std::numeric_limits<num_type>::min(),
                          num_type max = std::numeric_limits<num_type>::max())
      : unif(min, max), engine(std::random_device{}()) {}

  num_type min() const { return unif.min(); }

  num_type max() const { return unif.max(); }

  // generate a random number in [min(), max()].
  num_type operator()() { return unif(engine); }
};
#line 3 "Library/utils/read.hpp"
namespace workspace {
// read with std::cin.
template <class T = void>
struct read
{
    typename std::remove_const<T>::type value;
    template <class... types>
    read(types... args) : value(args...) { std::cin >> value; }
    operator T() const { return value; }
};
template <>
struct read<void>
{
    template <class T>
    operator T() const { T value; std::cin >> value; return value; }
};
} // namespace workspace
#line 4 "Library/utils/stream.hpp"

#line 6 "Library/utils/stream.hpp"
namespace std {
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ' ' << p.second;
}
template <class tuple_t, size_t index> struct tuple_is {
  static istream &apply(istream &is, tuple_t &t) {
    tuple_is<tuple_t, index - 1>::apply(is, t);
    return is >> get<index>(t);
  }
};
template <class tuple_t> struct tuple_is<tuple_t, SIZE_MAX> {
  static istream &apply(istream &is, tuple_t &t) { return is; }
};
template <class... T> istream &operator>>(istream &is, tuple<T...> &t) {
  return tuple_is<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is,
                                                                          t);
}
template <class tuple_t, size_t index> struct tuple_os {
  static ostream &apply(ostream &os, const tuple_t &t) {
    tuple_os<tuple_t, index - 1>::apply(os, t);
    return os << ' ' << get<index>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, 0> {
  static ostream &apply(ostream &os, const tuple_t &t) {
    return os << get<0>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, SIZE_MAX> {
  static ostream &apply(ostream &os, const tuple_t &t) { return os; }
};
template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) {
  return tuple_os<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os,
                                                                          t);
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   istream &>::type
operator>>(istream &is, Container &cont) {
  for (auto &&e : cont) is >> e;
  return is;
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   ostream &>::type
operator<<(ostream &os, const Container &cont) {
  bool head = true;
  for (auto &&e : cont) head ? head = 0 : (os << ' ', 0), os << e;
  return os;
}
}  // namespace std
#line 4 "Library/utils/trinary_search.hpp"
// trinary search on discrete range.
template <class iter_type, class comp_type>
iter_type trinary(iter_type first, iter_type last, comp_type comp)
{
    assert(first < last);
    intmax_t dist(last - first);
    while(dist > 2)
    {
        iter_type left(first + dist / 3), right(first + dist * 2 / 3);
        if(comp(left, right)) last = right, dist = dist * 2 / 3;
        else first = left, dist -= dist / 3;
    }
    if(dist > 1 && comp(first + 1, first)) ++first;
    return first;
}
// trinary search on real numbers.
template <class comp_type>
long double trinary(long double first, long double last, const long double eps, comp_type comp)
{
    assert(first < last);
    while(last - first > eps)
    {
        long double left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
        if(comp(left, right)) last = right;
        else first = left;
    }
    return first;
}
#line 2 "Library/utils/wrapper.hpp"
template <class Container> class reversed {
  Container &ref, copy;

 public:
  reversed(Container &ref) : ref(ref) {}
  reversed(Container &&ref = Container()) : ref(copy), copy(ref) {}
  auto begin() const { return ref.rbegin(); }
  auto end() const { return ref.rend(); }
};
#line 9 "other/h.cpp"

namespace workspace {
void main();
}
int main() { config::loop(workspace::main); }

unsigned config::cases() {
  // return -1; // unspecified
  // int t; std::cin >> t; return t; // given
  return 1;
}

#line 4 "Library/graph/directed/flow/min_cost_flow.hpp"

#line 4 "Library/graph/directed/flow/base.hpp"
// the base class of flow algorithms.
template <class cap_t, class cost_t> struct flow_base {
  struct edge_t {
    size_t src, dst;
    cap_t cap;
    cost_t cost;
    edge_t *rev;
    edge_t() = default;
    edge_t(size_t src, size_t dst, const cap_t &cap, edge_t *rev)
        : src(src), dst(dst), cap(cap), rev(rev) {}
    edge_t(size_t src, size_t dst, const cap_t &cap, const cost_t &cost,
           edge_t *rev)
        : src(src), dst(dst), cap(cap), cost(cost), rev(rev) {}
    const cap_t &flow(const cap_t &f = 0) { return cap -= f, rev->cap += f; }
    bool avbl() const { return static_cast<cap_t>(0) < cap; }
  };  // class edge_t

  class adj_type {
    edge_t *fst, *lst, *clst;

   public:
    template <class... Args> edge_t *emplace(Args &&... args) {
      if (lst == clst) {
        size_t len(clst - fst);
        edge_t *nfst = lst = new edge_t[len << 1];
        for (edge_t *p{fst}; p != clst; ++p, ++lst)
          p->rev->rev = lst, *lst = *p;
        delete[] fst;
        fst = nfst;
        clst = lst + len;
      }
      *lst = edge_t(args...);
      return lst++;
    }
    adj_type() : fst(new edge_t[1]), lst(fst), clst(fst + 1) {}
    ~adj_type() { delete[] fst; }
    edge_t &operator[](size_t i) {
      assert(i < size());
      return *(fst + i);
    }
    size_t size() const { return lst - fst; }
    edge_t *begin() const { return fst; }
    edge_t *end() const { return lst; }
  };  // class adj_type

  flow_base(size_t n = 0) : adjs(n) {}

  flow_base(const flow_base &other) : adjs(other.size()) {
    for (size_t node{}; node != size(); ++node)
      for (const auto &[src, dst, cap, cost, rev] : other[node])
        if (src == node) {
          edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
          ptr->rev = adjs[dst].emplace(dst, src, rev->cap, -cost, ptr);
          rev->src = nil;
        } else {
          rev->rev->src = node;
        }
  }

  flow_base &operator=(const flow_base &rhs) {
    if (this != &rhs) adjs.swap(flow_base(rhs).adjs);
    return *this;
  }

  size_t size() const { return adjs.size(); }

  adj_type &operator[](size_t node) {
    assert(node < size());
    return adjs[node];
  }
  const adj_type &operator[](size_t node) const {
    assert(node < size());
    return adjs[node];
  }

  virtual edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                           const cost_t &cost) {
    assert(src < size());
    assert(dst < size());
    assert(!(cap < static_cast<cap_t>(0)));
    if (!(static_cast<cap_t>(0) < cap) || src == dst) return nullptr;
    edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
    ptr->rev = adjs[dst].emplace(dst, src, 0, -cost, ptr);
    return ptr;
  }

 protected:
  constexpr static size_t nil = -1;
  std::vector<adj_type> adjs;
};  // class flow_base
#line 6 "Library/graph/directed/flow/min_cost_flow.hpp"
// Successive shortest paths algorithm.
template <class cap_t, class cost_t, bool density_tag = false>
class min_cost_flow : public flow_base<cap_t, cost_t> {
  using base = flow_base<cap_t, cost_t>;
  using edge_t = typename base::edge_t;
  using base::adjs;
  using base::nil;

  cost_t min_cost, total_cost;
  std::vector<cap_t> supp;
  std::vector<cost_t> ptnl;

  void copy_member(const min_cost_flow &other) {
    min_cost = other.min_cost;
    total_cost = other.total_cost;
    supp = other.supp;
    ptnl = other.ptnl;
  }

  void Dijkstra(std::vector<edge_t *> &last) {
    const cost_t infty(total_cost + 1);
    std::vector<cost_t> nptnl(size(), infty);
    if constexpr (density_tag) {
      // O(V^2)
      std::vector<bool> used(size());
      for (size_t src{}; src != size(); ++src) {
        if (static_cast<cap_t>(0) < supp[src]) {
          used[src] = true;
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (static_cast<cap_t>(0) < supp[e.dst]) continue;
            if (e.avbl() && e.cost < nptnl[e.dst]) {
              nptnl[e.dst] = e.cost;
              last[e.dst] = &e;
            }
          }
        }
      }
      for (;;) {
        size_t src{nil};
        cost_t sp{infty};
        for (size_t node{}; node != size(); ++node) {
          if (used[node] || nptnl[node] == infty) continue;
          cost_t dist{nptnl[node] - ptnl[node]};
          if (dist < sp) {
            sp = dist;
            src = node;
          }
        }
        if (src == nil) break;
        used[src] = true;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[src] + e.cost < nptnl[e.dst]) {
            nptnl[e.dst] = nptnl[src] + e.cost;
            last[e.dst] = &e;
          }
        }
      }
    } else {
      // O((V + E)logV)
      struct node_t {
        size_t id;
        cost_t dist;
        node_t(size_t id, cost_t dist) : id(id), dist(dist) {}
        bool operator<(const node_t &rhs) const { return rhs.dist < dist; }
      };
      std::priority_queue<node_t> que;
      for (size_t src{}; src != size(); ++src) {
        if (supp[src] > static_cast<cap_t>(0)) {
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (supp[e.dst] > static_cast<cap_t>(0)) continue;
            if (e.avbl() && nptnl[e.dst] > e.cost) {
              que.emplace(e.dst, (nptnl[e.dst] = e.cost) - ptnl[e.dst]);
              last[e.dst] = &e;
            }
          }
        }
      }
      while (!que.empty()) {
        auto [src, ndist] = que.top();
        que.pop();
        if (ndist + ptnl[src] != nptnl[src]) continue;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[e.dst] > nptnl[src] + e.cost) {
            que.emplace(e.dst,
                        (nptnl[e.dst] = nptnl[src] + e.cost) - ptnl[e.dst]);
            last[e.dst] = &e;
          }
        }
      }
    }
    ptnl.swap(nptnl);
  }

 public:
  using base::size;

  min_cost_flow(size_t n = 0)
      : base::flow_base(n), min_cost(0), total_cost(0), supp(n), ptnl(n) {}

  min_cost_flow(const min_cost_flow &other) : base::flow_base(other) {
    copy_member(other);
  }

  min_cost_flow &operator=(const min_cost_flow &other) {
    base::operator=(other);
    copy_member(other);
    return *this;
  }

  edge_t *add_edge(size_t src, size_t dst, const cost_t &cost);

  edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                   const cost_t &cost) override {
    assert(src != dst);
    if (cost < static_cast<cost_t>(0)) {
      supp[src] -= cap;
      supp[dst] += cap;
      min_cost += cap * cost;
      total_cost -= cap * cost;
      return base::add_edge(dst, src, cap, -cost);
    }
    total_cost += cap * cost;
    return base::add_edge(src, dst, cap, cost);
  }

  edge_t *add_edge(size_t src, size_t dst, const cap_t &lower,
                   const cap_t &upper, const cost_t &cost) {
    assert(!(upper < lower));
    supp[src] -= lower;
    supp[dst] += lower;
    min_cost += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  const cap_t &supply(size_t node, const cap_t &vol = 0) {
    assert(node < size());
    return supp[node] += vol;
  }

  const cap_t &demand(size_t node, const cap_t &vol) {
    return supply(node, -vol);
  }

  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge_t *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_t dst{}; dst != size(); ++dst) {
        if (supp[dst] < static_cast<cap_t>(0) and last[dst]) {
          cap_t resid{-supp[dst]};
          size_t src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < supp[src])) {
              resid = supp[src];
              block = src;
            }
            for (edge_t *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            supp[src] -= resid;
            supp[dst] += resid;
            min_cost += ptnl[dst] * resid;
            aug = true;
          }
          if (~block) {
            for (size_t node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
          }
        }
      }
    }
    return std::none_of(begin(supp), end(supp),
                        [](const cap_t &s) { return s < 0 || 0 < s; });
  }

  cost_t optimal() {
    assert(flow());
    return min_cost;
  }
};  // class min_cost_flow
#line 22 "other/h.cpp"

namespace workspace {
void main() {
  // start here!
  const i64 inf = 1e10;
  int n, m, x;
  cin >> n >> m >> x;

  min_cost_flow<i64, i64> base(n * 3);
  // make
  {
    for (int i = 0; i < n; i++) {
      int a, b, p;
      cin >> a >> b >> p;
      base.add_edge(3 * i + 1, 3 * i, inf, p);
      base.add_edge(3 * i, 3 * i + 1, inf, -1);
      base.add_edge(3 * i + 1, 3 * i + 2, inf, 0);
      if (i) base.add_edge(3 * (i - 1), 3 * i, inf, 0);
      base.supply(3 * i, -a);
      base.supply(3 * i + 1, a - b);
      base.supply(3 * i + 2, b);
    }
  }
  for (auto j = 0; j < m; ++j) {
    int u, v, f;
    cin >> u >> v >> f;
    --u, --v;
    if (f > 0) {
      base.add_edge(3 * v, 3 * u + 2, inf, 1);
    } else {
      base.add_edge(3 * u + 2, 3 * v, inf, 0);
    }
  }

  auto ok = [&](int t) -> bool {
    auto mcf = base;
    for (int i = 0; i < n; i++) {
      mcf.add_edge(3 * i + 2, 0, inf, t);
    }
    if (mcf.flow()) {
      auto opt = mcf.optimal();
      return opt >= x;
    }
    return false;
  };

  auto ans = binary_search(x + 200 * (m + n) + 1, -1, ok);
  if (ans > x + 200 * (m + n))
    cout << "-1\n";
  else
    cout << ans << eol;
}
}
accuracy: 0.4222222222222222
time_ms: 40
memory_kb: 3680
final_rank: 18

code_snippet: #line 1 "other/h.cpp"
#include <bits/extc++.h>
#if __has_include(<bit>)
#include <bit>
#endif
#line 7 "Library/alias.hpp"
namespace workspace {
constexpr char eol = '\n';
using namespace std;
using i32 = int_least32_t;
using i64 = int_least64_t;
using i128 = __int128_t;
using u32 = uint_least32_t;
using u64 = uint_least64_t;
using u128 = __uint128_t;
template <class T, class Comp = less<T>>
using priority_queue = std::priority_queue<T, vector<T>, Comp>;
template <class T> using stack = std::stack<T, vector<T>>;
}  // namespace workspace
#line 5 "Library/config.hpp"
namespace config {
const auto start_time{std::chrono::system_clock::now()};
int64_t elapsed() {
  using namespace std::chrono;
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - start_time).count();
}
__attribute__((constructor)) void setup() {
  using namespace std;
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(15);
#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (cin >> bufc)
      cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}
unsigned cases(), caseid = 1;
template <class F> void loop(F main) {
  for (const unsigned total = cases(); caseid <= total; ++caseid) main();
}
}  // namespace config
#line 2 "Library/option.hpp"
#ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #pragma GCC target("avx,avx2")
    #pragma GCC optimize("unroll-loops")
#endif
#line 2 "Library/utils/binary_search.hpp"
#if __cplusplus >= 201703L
#include <cassert>
#include <cmath>
#include <vector>
namespace workspace {
// binary search on a discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, iter_type>, bool>,
    iter_type>
binary_search(iter_type ok, iter_type ng, pred_type pred) {
  assert(ok != ng);
  std::make_signed_t<decltype(ng - ok)> dist(ng - ok);
  while (1 < dist || dist < -1) {
    iter_type mid(ok + dist / 2);
    if (pred(mid))
      ok = mid, dist -= dist / 2;
    else
      ng = mid, dist /= 2;
  }
  return ok;
}
// parallel binary search on each discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<iter_type>>,
                     std::vector<bool>>,
                 std::vector<iter_type>>
binary_search(std::vector<std::pair<iter_type, iter_type>> ends,
              pred_type pred) {
  std::vector<iter_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      iter_type mid(ok + (ng - ok) / 2);
      if (mids[i] != mid) {
        all_found = false;
        mids[i] = mid;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
// binary search on a real number interval.
template <class real_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, real_type>, bool>,
    real_type>
binary_search(real_type ok, real_type ng, const real_type eps, pred_type pred) {
  assert(ok != ng);
  while (ok + eps < ng || ng + eps < ok) {
    real_type mid{(ok + ng) / 2};
    (pred(mid) ? ok : ng) = mid;
  }
  return ok;
}
// parallel binary search on each real interval.
template <class real_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<real_type>>,
                     std::vector<bool>>,
                 std::vector<real_type>>
binary_search(std::vector<std::pair<real_type, real_type>> ends,
              const real_type eps, pred_type pred) {
  std::vector<real_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      if (ok + eps < ng || ng + eps < ok) {
        all_found = false;
        mids[i] = (ok + ng) / 2;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
}  // namespace workspace
#endif
#line 3 "Library/utils/casefmt.hpp"
namespace workspace {
std::ostream &casefmt(std::ostream& os) { return os << "Case #" << config::caseid << ": "; }
} // namespace workspace
#line 3 "Library/utils/chval.hpp"
namespace workspace {
template <class T, class Comp = std::less<T>>
bool chle(T &x, const T &y, Comp comp = Comp()) {
  return comp(y, x) ? x = y, true : false;
}
template <class T, class Comp = std::less<T>>
bool chge(T &x, const T &y, Comp comp = Comp()) {
  return comp(x, y) ? x = y, true : false;
}
}  // namespace workspace
#line 5 "Library/utils/coordinate_compression.hpp"

template <class T> class coordinate_compression {
  std::vector<T> uniquely;
  std::vector<size_t> compressed;

 public:
  coordinate_compression(const std::vector<T> &raw)
      : uniquely(raw), compressed(raw.size()) {
    std::sort(uniquely.begin(), uniquely.end());
    uniquely.erase(std::unique(uniquely.begin(), uniquely.end()),
                   uniquely.end());
    for (size_t i = 0; i != size(); ++i)
      compressed[i] =
          std::lower_bound(uniquely.begin(), uniquely.end(), raw[i]) -
          uniquely.begin();
  }

  size_t operator[](const size_t idx) const {
    assert(idx < size());
    return compressed[idx];
  }

  size_t size() const { return compressed.size(); }

  size_t count() const { return uniquely.size(); }

  T value(const size_t ord) const {
    assert(ord < count());
    return uniquely[ord];
  }

  size_t order(const T &value) const {
    return std::lower_bound(uniquely.begin(), uniquely.end(), value) -
           uniquely.begin();
  }

  auto begin() { return compressed.begin(); }
  auto end() { return compressed.end(); }
  auto rbegin() { return compressed.rbegin(); }
  auto rend() { return compressed.rend(); }
};
#line 3 "Library/utils/fixed_point.hpp"
namespace workspace {
// specify the return type of lambda.
template <class lambda_type> class fixed_point {
  lambda_type func;

 public:
  fixed_point(lambda_type &&f) : func(std::move(f)) {}
  template <class... Args> auto operator()(Args &&... args) const {
    return func(*this, std::forward<Args>(args)...);
  }
};
}  // namespace workspace
#line 6 "Library/utils/hash.hpp"

#line 3 "Library/utils/sfinae.hpp"
#include <type_traits>

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class T, class = int> struct mapped_of {
  using type = element_type<T>;
};
template <class T>
struct mapped_of<T,
                 typename std::pair<int, typename T::mapped_type>::first_type> {
  using type = typename T::mapped_type;
};
template <class T> using mapped_type = typename mapped_of<T>::type;

template <class T, class = void> struct is_integral_ext : std::false_type {};
template <class T>
struct is_integral_ext<
    T, typename std::enable_if<std::is_integral<T>::value>::type>
    : std::true_type {};
template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};
#if __cplusplus >= 201402
template <class T>
constexpr static bool is_integral_ext_v = is_integral_ext<T>::value;
#endif

template <typename T, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(2 < sizeof(T))>::type> {
  using type = uint_least64_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(4 < sizeof(T))>::type> {
  using type = __uint128_t;
};
#line 8 "Library/utils/hash.hpp"
namespace workspace {
template <class T, class = void> struct hash : std::hash<T> {};
#if __cplusplus >= 201703L
template <class Unique_bits_type>
struct hash<Unique_bits_type,
            enable_if_trait_type<Unique_bits_type,
                                 std::has_unique_object_representations>> {
  size_t operator()(uint64_t x) const {
    static const uint64_t m = std::random_device{}();
    x ^= x >> 23;
    x ^= m;
    x ^= x >> 47;
    return x - (x >> 32);
  }
};
#endif
template <class Key> size_t hash_combine(const size_t &seed, const Key &key) {
  return seed ^
         (hash<Key>()(key) + 0x9e3779b9 /* + (seed << 6) + (seed >> 2) */);
}
template <class T1, class T2> struct hash<std::pair<T1, T2>> {
  size_t operator()(const std::pair<T1, T2> &pair) const {
    return hash_combine(hash<T1>()(pair.first), pair.second);
  }
};
template <class... T> class hash<std::tuple<T...>> {
  template <class Tuple, size_t index = std::tuple_size<Tuple>::value - 1>
  struct tuple_hash {
    static uint64_t apply(const Tuple &t) {
      return hash_combine(tuple_hash<Tuple, index - 1>::apply(t),
                          std::get<index>(t));
    }
  };
  template <class Tuple> struct tuple_hash<Tuple, size_t(-1)> {
    static uint64_t apply(const Tuple &t) { return 0; }
  };

 public:
  uint64_t operator()(const std::tuple<T...> &t) const {
    return tuple_hash<std::tuple<T...>>::apply(t);
  }
};
template <class hash_table> struct hash_table_wrapper : hash_table {
  using key_type = typename hash_table::key_type;
  size_t count(const key_type &key) const {
    return hash_table::find(key) != hash_table::end();
  }
  template <class... Args> auto emplace(Args &&... args) {
    return hash_table::insert(typename hash_table::value_type(args...));
  }
};
template <class Key, class Mapped = __gnu_pbds::null_type>
using cc_hash_table =
    hash_table_wrapper<__gnu_pbds::cc_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped = __gnu_pbds::null_type>
using gp_hash_table =
    hash_table_wrapper<__gnu_pbds::gp_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped>
using unordered_map = std::unordered_map<Key, Mapped, hash<Key>>;
template <class Key> using unordered_set = std::unordered_set<Key, hash<Key>>;
}  // namespace workspace
#line 2 "Library/utils/make_vector.hpp"
#if __cplusplus >= 201703L
#include <vector>
namespace workspace {
template <typename T, size_t N>
constexpr auto make_vector(size_t* sizes, T const& init = T()) {
  if constexpr (N)
    return std::vector(*sizes, make_vector<T, N - 1>(std::next(sizes), init));
  else
    return init;
}
template <typename T, size_t N>
constexpr auto make_vector(const size_t (&sizes)[N], T const& init = T()) {
  return make_vector<T, N>((size_t*)sizes, init);
}
}  // namespace workspace
#endif
#line 3 "Library/utils/random_number_generator.hpp"
template <typename num_type> class random_number_generator {
  typename std::conditional<std::is_integral<num_type>::value,
                            std::uniform_int_distribution<num_type>,
                            std::uniform_real_distribution<num_type>>::type
      unif;

  std::mt19937 engine;

 public:
  random_number_generator(num_type min = std::numeric_limits<num_type>::min(),
                          num_type max = std::numeric_limits<num_type>::max())
      : unif(min, max), engine(std::random_device{}()) {}

  num_type min() const { return unif.min(); }

  num_type max() const { return unif.max(); }

  // generate a random number in [min(), max()].
  num_type operator()() { return unif(engine); }
};
#line 3 "Library/utils/read.hpp"
namespace workspace {
// read with std::cin.
template <class T = void>
struct read
{
    typename std::remove_const<T>::type value;
    template <class... types>
    read(types... args) : value(args...) { std::cin >> value; }
    operator T() const { return value; }
};
template <>
struct read<void>
{
    template <class T>
    operator T() const { T value; std::cin >> value; return value; }
};
} // namespace workspace
#line 4 "Library/utils/stream.hpp"

#line 6 "Library/utils/stream.hpp"
namespace std {
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ' ' << p.second;
}
template <class tuple_t, size_t index> struct tuple_is {
  static istream &apply(istream &is, tuple_t &t) {
    tuple_is<tuple_t, index - 1>::apply(is, t);
    return is >> get<index>(t);
  }
};
template <class tuple_t> struct tuple_is<tuple_t, SIZE_MAX> {
  static istream &apply(istream &is, tuple_t &t) { return is; }
};
template <class... T> istream &operator>>(istream &is, tuple<T...> &t) {
  return tuple_is<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is,
                                                                          t);
}
template <class tuple_t, size_t index> struct tuple_os {
  static ostream &apply(ostream &os, const tuple_t &t) {
    tuple_os<tuple_t, index - 1>::apply(os, t);
    return os << ' ' << get<index>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, 0> {
  static ostream &apply(ostream &os, const tuple_t &t) {
    return os << get<0>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, SIZE_MAX> {
  static ostream &apply(ostream &os, const tuple_t &t) { return os; }
};
template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) {
  return tuple_os<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os,
                                                                          t);
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   istream &>::type
operator>>(istream &is, Container &cont) {
  for (auto &&e : cont) is >> e;
  return is;
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   ostream &>::type
operator<<(ostream &os, const Container &cont) {
  bool head = true;
  for (auto &&e : cont) head ? head = 0 : (os << ' ', 0), os << e;
  return os;
}
}  // namespace std
#line 4 "Library/utils/trinary_search.hpp"
// trinary search on discrete range.
template <class iter_type, class comp_type>
iter_type trinary(iter_type first, iter_type last, comp_type comp)
{
    assert(first < last);
    intmax_t dist(last - first);
    while(dist > 2)
    {
        iter_type left(first + dist / 3), right(first + dist * 2 / 3);
        if(comp(left, right)) last = right, dist = dist * 2 / 3;
        else first = left, dist -= dist / 3;
    }
    if(dist > 1 && comp(first + 1, first)) ++first;
    return first;
}
// trinary search on real numbers.
template <class comp_type>
long double trinary(long double first, long double last, const long double eps, comp_type comp)
{
    assert(first < last);
    while(last - first > eps)
    {
        long double left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
        if(comp(left, right)) last = right;
        else first = left;
    }
    return first;
}
#line 2 "Library/utils/wrapper.hpp"
template <class Container> class reversed {
  Container &ref, copy;

 public:
  reversed(Container &ref) : ref(ref) {}
  reversed(Container &&ref = Container()) : ref(copy), copy(ref) {}
  auto begin() const { return ref.rbegin(); }
  auto end() const { return ref.rend(); }
};
#line 9 "other/h.cpp"

namespace workspace {
void main();
}
int main() { config::loop(workspace::main); }

unsigned config::cases() {
  // return -1; // unspecified
  // int t; std::cin >> t; return t; // given
  return 1;
}

#line 4 "Library/graph/directed/flow/min_cost_flow.hpp"

#line 4 "Library/graph/directed/flow/base.hpp"
// the base class of flow algorithms.
template <class cap_t, class cost_t> struct flow_base {
  struct edge_t {
    size_t src, dst;
    cap_t cap;
    cost_t cost;
    edge_t *rev;
    edge_t() = default;
    edge_t(size_t src, size_t dst, const cap_t &cap, edge_t *rev)
        : src(src), dst(dst), cap(cap), rev(rev) {}
    edge_t(size_t src, size_t dst, const cap_t &cap, const cost_t &cost,
           edge_t *rev)
        : src(src), dst(dst), cap(cap), cost(cost), rev(rev) {}
    const cap_t &flow(const cap_t &f = 0) { return cap -= f, rev->cap += f; }
    bool avbl() const { return static_cast<cap_t>(0) < cap; }
  };  // class edge_t

  class adj_type {
    edge_t *fst, *lst, *clst;

   public:
    template <class... Args> edge_t *emplace(Args &&... args) {
      if (lst == clst) {
        size_t len(clst - fst);
        edge_t *nfst = lst = new edge_t[len << 1];
        for (edge_t *p{fst}; p != clst; ++p, ++lst)
          p->rev->rev = lst, *lst = *p;
        delete[] fst;
        fst = nfst;
        clst = lst + len;
      }
      *lst = edge_t(args...);
      return lst++;
    }
    adj_type() : fst(new edge_t[1]), lst(fst), clst(fst + 1) {}
    ~adj_type() { delete[] fst; }
    edge_t &operator[](size_t i) {
      assert(i < size());
      return *(fst + i);
    }
    size_t size() const { return lst - fst; }
    edge_t *begin() const { return fst; }
    edge_t *end() const { return lst; }
  };  // class adj_type

  flow_base(size_t n = 0) : adjs(n) {}

  flow_base(const flow_base &other) : adjs(other.size()) {
    for (size_t node{}; node != size(); ++node)
      for (const auto &[src, dst, cap, cost, rev] : other[node])
        if (src == node) {
          edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
          ptr->rev = adjs[dst].emplace(dst, src, rev->cap, -cost, ptr);
          rev->src = nil;
        } else {
          rev->rev->src = node;
        }
  }

  flow_base &operator=(const flow_base &rhs) {
    if (this != &rhs) adjs.swap(flow_base(rhs).adjs);
    return *this;
  }

  size_t size() const { return adjs.size(); }

  adj_type &operator[](size_t node) {
    assert(node < size());
    return adjs[node];
  }
  const adj_type &operator[](size_t node) const {
    assert(node < size());
    return adjs[node];
  }

  virtual edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                           const cost_t &cost) {
    assert(src < size());
    assert(dst < size());
    assert(!(cap < static_cast<cap_t>(0)));
    if (!(static_cast<cap_t>(0) < cap) || src == dst) return nullptr;
    edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
    ptr->rev = adjs[dst].emplace(dst, src, 0, -cost, ptr);
    return ptr;
  }

 protected:
  constexpr static size_t nil = -1;
  std::vector<adj_type> adjs;
};  // class flow_base
#line 6 "Library/graph/directed/flow/min_cost_flow.hpp"
// Successive shortest paths algorithm.
template <class cap_t, class cost_t, bool density_tag = false>
class min_cost_flow : public flow_base<cap_t, cost_t> {
  using base = flow_base<cap_t, cost_t>;
  using edge_t = typename base::edge_t;
  using base::adjs;
  using base::nil;

  cost_t min_cost, total_cost;
  std::vector<cap_t> supp;
  std::vector<cost_t> ptnl;

  void copy_member(const min_cost_flow &other) {
    min_cost = other.min_cost;
    total_cost = other.total_cost;
    supp = other.supp;
    ptnl = other.ptnl;
  }

  void Dijkstra(std::vector<edge_t *> &last) {
    const cost_t infty(total_cost + 1);
    std::vector<cost_t> nptnl(size(), infty);
    if constexpr (density_tag) {
      // O(V^2)
      std::vector<bool> used(size());
      for (size_t src{}; src != size(); ++src) {
        if (static_cast<cap_t>(0) < supp[src]) {
          used[src] = true;
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (static_cast<cap_t>(0) < supp[e.dst]) continue;
            if (e.avbl() && e.cost < nptnl[e.dst]) {
              nptnl[e.dst] = e.cost;
              last[e.dst] = &e;
            }
          }
        }
      }
      for (;;) {
        size_t src{nil};
        cost_t sp{infty};
        for (size_t node{}; node != size(); ++node) {
          if (used[node] || nptnl[node] == infty) continue;
          cost_t dist{nptnl[node] - ptnl[node]};
          if (dist < sp) {
            sp = dist;
            src = node;
          }
        }
        if (src == nil) break;
        used[src] = true;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[src] + e.cost < nptnl[e.dst]) {
            nptnl[e.dst] = nptnl[src] + e.cost;
            last[e.dst] = &e;
          }
        }
      }
    } else {
      // O((V + E)logV)
      struct node_t {
        size_t id;
        cost_t dist;
        node_t(size_t id, cost_t dist) : id(id), dist(dist) {}
        bool operator<(const node_t &rhs) const { return rhs.dist < dist; }
      };
      std::priority_queue<node_t> que;
      for (size_t src{}; src != size(); ++src) {
        if (supp[src] > static_cast<cap_t>(0)) {
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (supp[e.dst] > static_cast<cap_t>(0)) continue;
            if (e.avbl() && nptnl[e.dst] > e.cost) {
              que.emplace(e.dst, (nptnl[e.dst] = e.cost) - ptnl[e.dst]);
              last[e.dst] = &e;
            }
          }
        }
      }
      while (!que.empty()) {
        auto [src, ndist] = que.top();
        que.pop();
        if (ndist + ptnl[src] != nptnl[src]) continue;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[e.dst] > nptnl[src] + e.cost) {
            que.emplace(e.dst,
                        (nptnl[e.dst] = nptnl[src] + e.cost) - ptnl[e.dst]);
            last[e.dst] = &e;
          }
        }
      }
    }
    ptnl.swap(nptnl);
  }

 public:
  using base::size;

  min_cost_flow(size_t n = 0)
      : base::flow_base(n), min_cost(0), total_cost(0), supp(n), ptnl(n) {}

  min_cost_flow(const min_cost_flow &other) : base::flow_base(other) {
    copy_member(other);
  }

  min_cost_flow &operator=(const min_cost_flow &other) {
    base::operator=(other);
    copy_member(other);
    return *this;
  }

  edge_t *add_edge(size_t src, size_t dst, const cost_t &cost);

  edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                   const cost_t &cost) override {
    assert(src != dst);
    if (cost < static_cast<cost_t>(0)) {
      supp[src] -= cap;
      supp[dst] += cap;
      min_cost += cap * cost;
      total_cost -= cap * cost;
      return base::add_edge(dst, src, cap, -cost);
    }
    total_cost += cap * cost;
    return base::add_edge(src, dst, cap, cost);
  }

  edge_t *add_edge(size_t src, size_t dst, const cap_t &lower,
                   const cap_t &upper, const cost_t &cost) {
    assert(!(upper < lower));
    supp[src] -= lower;
    supp[dst] += lower;
    min_cost += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  const cap_t &supply(size_t node, const cap_t &vol = 0) {
    assert(node < size());
    return supp[node] += vol;
  }

  const cap_t &demand(size_t node, const cap_t &vol) {
    return supply(node, -vol);
  }

  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge_t *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_t dst{}; dst != size(); ++dst) {
        if (supp[dst] < static_cast<cap_t>(0) and last[dst]) {
          cap_t resid{-supp[dst]};
          size_t src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < supp[src])) {
              resid = supp[src];
              block = src;
            }
            for (edge_t *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            supp[src] -= resid;
            supp[dst] += resid;
            min_cost += ptnl[dst] * resid;
            aug = true;
          }
          if (~block) {
            for (size_t node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
          }
        }
      }
    }
    return std::none_of(begin(supp), end(supp),
                        [](const cap_t &s) { return s < 0 || 0 < s; });
  }

  cost_t optimal() {
    assert(flow());
    return min_cost;
  }
};  // class min_cost_flow
#line 22 "other/h.cpp"

namespace workspace {
void main() {
  // start here!
  const i64 inf = 1e10;
  int n, m, x;
  cin >> n >> m >> x;

  min_cost_flow<i64, i64> base(n * 3);
  // make
  {
    for (int i = 0; i < n; i++) {
      int a, b, p;
      cin >> a >> b >> p;
      base.add_edge(3 * i + 1, 3 * i, inf, p);
      base.add_edge(3 * i, 3 * i + 1, inf, -1);
      base.add_edge(3 * i + 1, 3 * i + 2, inf, 0);
      if (i) base.add_edge(3 * (i - 1), 3 * i, inf, 0);
      base.supply(3 * i, -a);
      base.supply(3 * i + 1, a - b);
      base.supply(3 * i + 2, b);
    }
  }
  for (auto j = 0; j < m; ++j) {
    int u, v, f;
    cin >> u >> v >> f;
    --u, --v;
    if (f > 0) {
      base.add_edge(3 * v, 3 * u + 2, inf, 1);
    } else {
      base.add_edge(3 * u + 2, 3 * v, inf, 0);
    }
  }

  auto ok = [&](int t) -> bool {
    auto mcf = base;
    for (int i = 0; i < n; i++) {
      mcf.add_edge(3 * i + 2, 0, inf, t);
    }
    if (mcf.flow()) {
      auto opt = mcf.optimal();
      return opt >= x;
    }
    return false;
  };

  auto ans = binary_search(x + 100 * (m + n) + 1, -1, ok);
  if (ans > x + 100 * (m + n))
    cout << "-1\n";
  else
    cout << ans << eol;
}
}
accuracy: 0.4222222222222222
time_ms: 40
memory_kb: 3604
final_rank: 15

code_snippet: #line 1 "other/h.cpp"
#include <bits/extc++.h>
#if __has_include(<bit>)
#include <bit>
#endif
#line 7 "Library/alias.hpp"
namespace workspace {
constexpr char eol = '\n';
using namespace std;
using i32 = int_least32_t;
using i64 = int_least64_t;
using i128 = __int128_t;
using u32 = uint_least32_t;
using u64 = uint_least64_t;
using u128 = __uint128_t;
template <class T, class Comp = less<T>>
using priority_queue = std::priority_queue<T, vector<T>, Comp>;
template <class T> using stack = std::stack<T, vector<T>>;
}  // namespace workspace
#line 5 "Library/config.hpp"
namespace config {
const auto start_time{std::chrono::system_clock::now()};
int64_t elapsed() {
  using namespace std::chrono;
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - start_time).count();
}
__attribute__((constructor)) void setup() {
  using namespace std;
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(15);
#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (cin >> bufc)
      cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}
unsigned cases(), caseid = 1;
template <class F> void loop(F main) {
  for (const unsigned total = cases(); caseid <= total; ++caseid) main();
}
}  // namespace config
#line 2 "Library/option.hpp"
#ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #pragma GCC target("avx,avx2")
    #pragma GCC optimize("unroll-loops")
#endif
#line 2 "Library/utils/binary_search.hpp"
#if __cplusplus >= 201703L
#include <cassert>
#include <cmath>
#include <vector>
namespace workspace {
// binary search on a discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, iter_type>, bool>,
    iter_type>
binary_search(iter_type ok, iter_type ng, pred_type pred) {
  assert(ok != ng);
  std::make_signed_t<decltype(ng - ok)> dist(ng - ok);
  while (1 < dist || dist < -1) {
    iter_type mid(ok + dist / 2);
    if (pred(mid))
      ok = mid, dist -= dist / 2;
    else
      ng = mid, dist /= 2;
  }
  return ok;
}
// parallel binary search on each discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<iter_type>>,
                     std::vector<bool>>,
                 std::vector<iter_type>>
binary_search(std::vector<std::pair<iter_type, iter_type>> ends,
              pred_type pred) {
  std::vector<iter_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      iter_type mid(ok + (ng - ok) / 2);
      if (mids[i] != mid) {
        all_found = false;
        mids[i] = mid;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
// binary search on a real number interval.
template <class real_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, real_type>, bool>,
    real_type>
binary_search(real_type ok, real_type ng, const real_type eps, pred_type pred) {
  assert(ok != ng);
  while (ok + eps < ng || ng + eps < ok) {
    real_type mid{(ok + ng) / 2};
    (pred(mid) ? ok : ng) = mid;
  }
  return ok;
}
// parallel binary search on each real interval.
template <class real_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<real_type>>,
                     std::vector<bool>>,
                 std::vector<real_type>>
binary_search(std::vector<std::pair<real_type, real_type>> ends,
              const real_type eps, pred_type pred) {
  std::vector<real_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      if (ok + eps < ng || ng + eps < ok) {
        all_found = false;
        mids[i] = (ok + ng) / 2;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
}  // namespace workspace
#endif
#line 3 "Library/utils/casefmt.hpp"
namespace workspace {
std::ostream &casefmt(std::ostream& os) { return os << "Case #" << config::caseid << ": "; }
} // namespace workspace
#line 3 "Library/utils/chval.hpp"
namespace workspace {
template <class T, class Comp = std::less<T>>
bool chle(T &x, const T &y, Comp comp = Comp()) {
  return comp(y, x) ? x = y, true : false;
}
template <class T, class Comp = std::less<T>>
bool chge(T &x, const T &y, Comp comp = Comp()) {
  return comp(x, y) ? x = y, true : false;
}
}  // namespace workspace
#line 5 "Library/utils/coordinate_compression.hpp"

template <class T> class coordinate_compression {
  std::vector<T> uniquely;
  std::vector<size_t> compressed;

 public:
  coordinate_compression(const std::vector<T> &raw)
      : uniquely(raw), compressed(raw.size()) {
    std::sort(uniquely.begin(), uniquely.end());
    uniquely.erase(std::unique(uniquely.begin(), uniquely.end()),
                   uniquely.end());
    for (size_t i = 0; i != size(); ++i)
      compressed[i] =
          std::lower_bound(uniquely.begin(), uniquely.end(), raw[i]) -
          uniquely.begin();
  }

  size_t operator[](const size_t idx) const {
    assert(idx < size());
    return compressed[idx];
  }

  size_t size() const { return compressed.size(); }

  size_t count() const { return uniquely.size(); }

  T value(const size_t ord) const {
    assert(ord < count());
    return uniquely[ord];
  }

  size_t order(const T &value) const {
    return std::lower_bound(uniquely.begin(), uniquely.end(), value) -
           uniquely.begin();
  }

  auto begin() { return compressed.begin(); }
  auto end() { return compressed.end(); }
  auto rbegin() { return compressed.rbegin(); }
  auto rend() { return compressed.rend(); }
};
#line 3 "Library/utils/fixed_point.hpp"
namespace workspace {
// specify the return type of lambda.
template <class lambda_type> class fixed_point {
  lambda_type func;

 public:
  fixed_point(lambda_type &&f) : func(std::move(f)) {}
  template <class... Args> auto operator()(Args &&... args) const {
    return func(*this, std::forward<Args>(args)...);
  }
};
}  // namespace workspace
#line 6 "Library/utils/hash.hpp"

#line 3 "Library/utils/sfinae.hpp"
#include <type_traits>

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class T, class = int> struct mapped_of {
  using type = element_type<T>;
};
template <class T>
struct mapped_of<T,
                 typename std::pair<int, typename T::mapped_type>::first_type> {
  using type = typename T::mapped_type;
};
template <class T> using mapped_type = typename mapped_of<T>::type;

template <class T, class = void> struct is_integral_ext : std::false_type {};
template <class T>
struct is_integral_ext<
    T, typename std::enable_if<std::is_integral<T>::value>::type>
    : std::true_type {};
template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};
#if __cplusplus >= 201402
template <class T>
constexpr static bool is_integral_ext_v = is_integral_ext<T>::value;
#endif

template <typename T, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(2 < sizeof(T))>::type> {
  using type = uint_least64_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(4 < sizeof(T))>::type> {
  using type = __uint128_t;
};
#line 8 "Library/utils/hash.hpp"
namespace workspace {
template <class T, class = void> struct hash : std::hash<T> {};
#if __cplusplus >= 201703L
template <class Unique_bits_type>
struct hash<Unique_bits_type,
            enable_if_trait_type<Unique_bits_type,
                                 std::has_unique_object_representations>> {
  size_t operator()(uint64_t x) const {
    static const uint64_t m = std::random_device{}();
    x ^= x >> 23;
    x ^= m;
    x ^= x >> 47;
    return x - (x >> 32);
  }
};
#endif
template <class Key> size_t hash_combine(const size_t &seed, const Key &key) {
  return seed ^
         (hash<Key>()(key) + 0x9e3779b9 /* + (seed << 6) + (seed >> 2) */);
}
template <class T1, class T2> struct hash<std::pair<T1, T2>> {
  size_t operator()(const std::pair<T1, T2> &pair) const {
    return hash_combine(hash<T1>()(pair.first), pair.second);
  }
};
template <class... T> class hash<std::tuple<T...>> {
  template <class Tuple, size_t index = std::tuple_size<Tuple>::value - 1>
  struct tuple_hash {
    static uint64_t apply(const Tuple &t) {
      return hash_combine(tuple_hash<Tuple, index - 1>::apply(t),
                          std::get<index>(t));
    }
  };
  template <class Tuple> struct tuple_hash<Tuple, size_t(-1)> {
    static uint64_t apply(const Tuple &t) { return 0; }
  };

 public:
  uint64_t operator()(const std::tuple<T...> &t) const {
    return tuple_hash<std::tuple<T...>>::apply(t);
  }
};
template <class hash_table> struct hash_table_wrapper : hash_table {
  using key_type = typename hash_table::key_type;
  size_t count(const key_type &key) const {
    return hash_table::find(key) != hash_table::end();
  }
  template <class... Args> auto emplace(Args &&... args) {
    return hash_table::insert(typename hash_table::value_type(args...));
  }
};
template <class Key, class Mapped = __gnu_pbds::null_type>
using cc_hash_table =
    hash_table_wrapper<__gnu_pbds::cc_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped = __gnu_pbds::null_type>
using gp_hash_table =
    hash_table_wrapper<__gnu_pbds::gp_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped>
using unordered_map = std::unordered_map<Key, Mapped, hash<Key>>;
template <class Key> using unordered_set = std::unordered_set<Key, hash<Key>>;
}  // namespace workspace
#line 2 "Library/utils/make_vector.hpp"
#if __cplusplus >= 201703L
#include <vector>
namespace workspace {
template <typename T, size_t N>
constexpr auto make_vector(size_t* sizes, T const& init = T()) {
  if constexpr (N)
    return std::vector(*sizes, make_vector<T, N - 1>(std::next(sizes), init));
  else
    return init;
}
template <typename T, size_t N>
constexpr auto make_vector(const size_t (&sizes)[N], T const& init = T()) {
  return make_vector<T, N>((size_t*)sizes, init);
}
}  // namespace workspace
#endif
#line 3 "Library/utils/random_number_generator.hpp"
template <typename num_type> class random_number_generator {
  typename std::conditional<std::is_integral<num_type>::value,
                            std::uniform_int_distribution<num_type>,
                            std::uniform_real_distribution<num_type>>::type
      unif;

  std::mt19937 engine;

 public:
  random_number_generator(num_type min = std::numeric_limits<num_type>::min(),
                          num_type max = std::numeric_limits<num_type>::max())
      : unif(min, max), engine(std::random_device{}()) {}

  num_type min() const { return unif.min(); }

  num_type max() const { return unif.max(); }

  // generate a random number in [min(), max()].
  num_type operator()() { return unif(engine); }
};
#line 3 "Library/utils/read.hpp"
namespace workspace {
// read with std::cin.
template <class T = void>
struct read
{
    typename std::remove_const<T>::type value;
    template <class... types>
    read(types... args) : value(args...) { std::cin >> value; }
    operator T() const { return value; }
};
template <>
struct read<void>
{
    template <class T>
    operator T() const { T value; std::cin >> value; return value; }
};
} // namespace workspace
#line 4 "Library/utils/stream.hpp"

#line 6 "Library/utils/stream.hpp"
namespace std {
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ' ' << p.second;
}
template <class tuple_t, size_t index> struct tuple_is {
  static istream &apply(istream &is, tuple_t &t) {
    tuple_is<tuple_t, index - 1>::apply(is, t);
    return is >> get<index>(t);
  }
};
template <class tuple_t> struct tuple_is<tuple_t, SIZE_MAX> {
  static istream &apply(istream &is, tuple_t &t) { return is; }
};
template <class... T> istream &operator>>(istream &is, tuple<T...> &t) {
  return tuple_is<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is,
                                                                          t);
}
template <class tuple_t, size_t index> struct tuple_os {
  static ostream &apply(ostream &os, const tuple_t &t) {
    tuple_os<tuple_t, index - 1>::apply(os, t);
    return os << ' ' << get<index>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, 0> {
  static ostream &apply(ostream &os, const tuple_t &t) {
    return os << get<0>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, SIZE_MAX> {
  static ostream &apply(ostream &os, const tuple_t &t) { return os; }
};
template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) {
  return tuple_os<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os,
                                                                          t);
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   istream &>::type
operator>>(istream &is, Container &cont) {
  for (auto &&e : cont) is >> e;
  return is;
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   ostream &>::type
operator<<(ostream &os, const Container &cont) {
  bool head = true;
  for (auto &&e : cont) head ? head = 0 : (os << ' ', 0), os << e;
  return os;
}
}  // namespace std
#line 4 "Library/utils/trinary_search.hpp"
// trinary search on discrete range.
template <class iter_type, class comp_type>
iter_type trinary(iter_type first, iter_type last, comp_type comp)
{
    assert(first < last);
    intmax_t dist(last - first);
    while(dist > 2)
    {
        iter_type left(first + dist / 3), right(first + dist * 2 / 3);
        if(comp(left, right)) last = right, dist = dist * 2 / 3;
        else first = left, dist -= dist / 3;
    }
    if(dist > 1 && comp(first + 1, first)) ++first;
    return first;
}
// trinary search on real numbers.
template <class comp_type>
long double trinary(long double first, long double last, const long double eps, comp_type comp)
{
    assert(first < last);
    while(last - first > eps)
    {
        long double left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
        if(comp(left, right)) last = right;
        else first = left;
    }
    return first;
}
#line 2 "Library/utils/wrapper.hpp"
template <class Container> class reversed {
  Container &ref, copy;

 public:
  reversed(Container &ref) : ref(ref) {}
  reversed(Container &&ref = Container()) : ref(copy), copy(ref) {}
  auto begin() const { return ref.rbegin(); }
  auto end() const { return ref.rend(); }
};
#line 9 "other/h.cpp"

namespace workspace {
void main();
}
int main() { config::loop(workspace::main); }

unsigned config::cases() {
  // return -1; // unspecified
  // int t; std::cin >> t; return t; // given
  return 1;
}

#line 4 "Library/graph/directed/flow/min_cost_flow.hpp"

#line 4 "Library/graph/directed/flow/base.hpp"
// the base class of flow algorithms.
template <class cap_t, class cost_t> struct flow_base {
  struct edge_t {
    size_t src, dst;
    cap_t cap;
    cost_t cost;
    edge_t *rev;
    edge_t() = default;
    edge_t(size_t src, size_t dst, const cap_t &cap, edge_t *rev)
        : src(src), dst(dst), cap(cap), rev(rev) {}
    edge_t(size_t src, size_t dst, const cap_t &cap, const cost_t &cost,
           edge_t *rev)
        : src(src), dst(dst), cap(cap), cost(cost), rev(rev) {}
    const cap_t &flow(const cap_t &f = 0) { return cap -= f, rev->cap += f; }
    bool avbl() const { return static_cast<cap_t>(0) < cap; }
  };  // class edge_t

  class adj_type {
    edge_t *fst, *lst, *clst;

   public:
    template <class... Args> edge_t *emplace(Args &&... args) {
      if (lst == clst) {
        size_t len(clst - fst);
        edge_t *nfst = lst = new edge_t[len << 1];
        for (edge_t *p{fst}; p != clst; ++p, ++lst)
          p->rev->rev = lst, *lst = *p;
        delete[] fst;
        fst = nfst;
        clst = lst + len;
      }
      *lst = edge_t(args...);
      return lst++;
    }
    adj_type() : fst(new edge_t[1]), lst(fst), clst(fst + 1) {}
    ~adj_type() { delete[] fst; }
    edge_t &operator[](size_t i) {
      assert(i < size());
      return *(fst + i);
    }
    size_t size() const { return lst - fst; }
    edge_t *begin() const { return fst; }
    edge_t *end() const { return lst; }
  };  // class adj_type

  flow_base(size_t n = 0) : adjs(n) {}

  flow_base(const flow_base &other) : adjs(other.size()) {
    for (size_t node{}; node != size(); ++node)
      for (const auto &[src, dst, cap, cost, rev] : other[node])
        if (src == node) {
          edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
          ptr->rev = adjs[dst].emplace(dst, src, rev->cap, -cost, ptr);
          rev->src = nil;
        } else {
          rev->rev->src = node;
        }
  }

  flow_base &operator=(const flow_base &rhs) {
    if (this != &rhs) adjs.swap(flow_base(rhs).adjs);
    return *this;
  }

  size_t size() const { return adjs.size(); }

  adj_type &operator[](size_t node) {
    assert(node < size());
    return adjs[node];
  }
  const adj_type &operator[](size_t node) const {
    assert(node < size());
    return adjs[node];
  }

  virtual edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                           const cost_t &cost) {
    assert(src < size());
    assert(dst < size());
    assert(!(cap < static_cast<cap_t>(0)));
    if (!(static_cast<cap_t>(0) < cap) || src == dst) return nullptr;
    edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
    ptr->rev = adjs[dst].emplace(dst, src, 0, -cost, ptr);
    return ptr;
  }

 protected:
  constexpr static size_t nil = -1;
  std::vector<adj_type> adjs;
};  // class flow_base
#line 6 "Library/graph/directed/flow/min_cost_flow.hpp"
// Successive shortest paths algorithm.
template <class cap_t, class cost_t, bool density_tag = false>
class min_cost_flow : public flow_base<cap_t, cost_t> {
  using base = flow_base<cap_t, cost_t>;
  using edge_t = typename base::edge_t;
  using base::adjs;
  using base::nil;

  cost_t min_cost, total_cost;
  std::vector<cap_t> supp;
  std::vector<cost_t> ptnl;

  void copy_member(const min_cost_flow &other) {
    min_cost = other.min_cost;
    total_cost = other.total_cost;
    supp = other.supp;
    ptnl = other.ptnl;
  }

  void Dijkstra(std::vector<edge_t *> &last) {
    const cost_t infty(total_cost + 1);
    std::vector<cost_t> nptnl(size(), infty);
    if constexpr (density_tag) {
      // O(V^2)
      std::vector<bool> used(size());
      for (size_t src{}; src != size(); ++src) {
        if (static_cast<cap_t>(0) < supp[src]) {
          used[src] = true;
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (static_cast<cap_t>(0) < supp[e.dst]) continue;
            if (e.avbl() && e.cost < nptnl[e.dst]) {
              nptnl[e.dst] = e.cost;
              last[e.dst] = &e;
            }
          }
        }
      }
      for (;;) {
        size_t src{nil};
        cost_t sp{infty};
        for (size_t node{}; node != size(); ++node) {
          if (used[node] || nptnl[node] == infty) continue;
          cost_t dist{nptnl[node] - ptnl[node]};
          if (dist < sp) {
            sp = dist;
            src = node;
          }
        }
        if (src == nil) break;
        used[src] = true;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[src] + e.cost < nptnl[e.dst]) {
            nptnl[e.dst] = nptnl[src] + e.cost;
            last[e.dst] = &e;
          }
        }
      }
    } else {
      // O((V + E)logV)
      struct node_t {
        size_t id;
        cost_t dist;
        node_t(size_t id, cost_t dist) : id(id), dist(dist) {}
        bool operator<(const node_t &rhs) const { return rhs.dist < dist; }
      };
      std::priority_queue<node_t> que;
      for (size_t src{}; src != size(); ++src) {
        if (supp[src] > static_cast<cap_t>(0)) {
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (supp[e.dst] > static_cast<cap_t>(0)) continue;
            if (e.avbl() && nptnl[e.dst] > e.cost) {
              que.emplace(e.dst, (nptnl[e.dst] = e.cost) - ptnl[e.dst]);
              last[e.dst] = &e;
            }
          }
        }
      }
      while (!que.empty()) {
        auto [src, ndist] = que.top();
        que.pop();
        if (ndist + ptnl[src] != nptnl[src]) continue;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[e.dst] > nptnl[src] + e.cost) {
            que.emplace(e.dst,
                        (nptnl[e.dst] = nptnl[src] + e.cost) - ptnl[e.dst]);
            last[e.dst] = &e;
          }
        }
      }
    }
    ptnl.swap(nptnl);
  }

 public:
  using base::size;

  min_cost_flow(size_t n = 0)
      : base::flow_base(n), min_cost(0), total_cost(0), supp(n), ptnl(n) {}

  min_cost_flow(const min_cost_flow &other) : base::flow_base(other) {
    copy_member(other);
  }

  min_cost_flow &operator=(const min_cost_flow &other) {
    base::operator=(other);
    copy_member(other);
    return *this;
  }

  edge_t *add_edge(size_t src, size_t dst, const cost_t &cost);

  edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                   const cost_t &cost) override {
    assert(src != dst);
    if (cost < static_cast<cost_t>(0)) {
      supp[src] -= cap;
      supp[dst] += cap;
      min_cost += cap * cost;
      total_cost -= cap * cost;
      return base::add_edge(dst, src, cap, -cost);
    }
    total_cost += cap * cost;
    return base::add_edge(src, dst, cap, cost);
  }

  edge_t *add_edge(size_t src, size_t dst, const cap_t &lower,
                   const cap_t &upper, const cost_t &cost) {
    assert(!(upper < lower));
    supp[src] -= lower;
    supp[dst] += lower;
    min_cost += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  const cap_t &supply(size_t node, const cap_t &vol = 0) {
    assert(node < size());
    return supp[node] += vol;
  }

  const cap_t &demand(size_t node, const cap_t &vol) {
    return supply(node, -vol);
  }

  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge_t *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_t dst{}; dst != size(); ++dst) {
        if (supp[dst] < static_cast<cap_t>(0) and last[dst]) {
          cap_t resid{-supp[dst]};
          size_t src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < supp[src])) {
              resid = supp[src];
              block = src;
            }
            for (edge_t *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            supp[src] -= resid;
            supp[dst] += resid;
            min_cost += ptnl[dst] * resid;
            aug = true;
          }
          if (~block) {
            for (size_t node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
          }
        }
      }
    }
    return std::none_of(begin(supp), end(supp),
                        [](const cap_t &s) { return s < 0 || 0 < s; });
  }

  cost_t optimal() {
    assert(flow());
    return min_cost;
  }
};  // class min_cost_flow
#line 22 "other/h.cpp"

namespace workspace {
void main() {
  // start here!
  const i64 inf = 1e10;
  int n, m, x;
  cin >> n >> m >> x;

  min_cost_flow<i64, i64> base(n * 3);
  // make
  {
    for (int i = 0; i < n; i++) {
      int a, b, p;
      cin >> a >> b >> p;
      base.add_edge(3 * i + 1, 3 * i, inf, p);
      base.add_edge(3 * i, 3 * i + 1, inf, -1);
      base.add_edge(3 * i + 1, 3 * i + 2, inf, 0);
      if (i) base.add_edge(3 * (i - 1), 3 * i, inf, 0);
      base.supply(3 * i, -a);
      base.supply(3 * i + 1, a - b);
      base.supply(3 * i + 2, b);
    }
  }
  for (auto j = 0; j < m; ++j) {
    int u, v, f;
    cin >> u >> v >> f;
    --u, --v;
    if (f > 0) {
      base.add_edge(3 * v, 3 * u + 2, inf, 1);
    } else {
      base.add_edge(3 * u + 2, 3 * v, inf, 0);
    }
  }

  auto ok = [&](int t) -> bool {
    auto mcf = base;
    for (int i = 0; i < n; i++) {
      mcf.add_edge(3 * i + 2, 0, inf, t);
    }
    if (mcf.flow()) {
      auto opt = mcf.optimal();
      return opt >= x;
    }
    return false;
  };

  auto ans = binary_search(x + 100 * n + 1, -1, ok);
  if (ans > x + 100 * n)
    cout << "-1\n";
  else
    cout << ans << eol;
}
}
accuracy: 0.4222222222222222
time_ms: 40
memory_kb: 3580
final_rank: 13

code_snippet: #line 1 "other/h.cpp"
#include <bits/extc++.h>
#if __has_include(<bit>)
#include <bit>
#endif
#line 7 "Library/alias.hpp"
namespace workspace {
constexpr char eol = '\n';
using namespace std;
using i32 = int_least32_t;
using i64 = int_least64_t;
using i128 = __int128_t;
using u32 = uint_least32_t;
using u64 = uint_least64_t;
using u128 = __uint128_t;
template <class T, class Comp = less<T>>
using priority_queue = std::priority_queue<T, vector<T>, Comp>;
template <class T> using stack = std::stack<T, vector<T>>;
}  // namespace workspace
#line 5 "Library/config.hpp"
namespace config {
const auto start_time{std::chrono::system_clock::now()};
int64_t elapsed() {
  using namespace std::chrono;
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - start_time).count();
}
__attribute__((constructor)) void setup() {
  using namespace std;
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(15);
#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (cin >> bufc)
      cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}
unsigned cases(), caseid = 1;
template <class F> void loop(F main) {
  for (const unsigned total = cases(); caseid <= total; ++caseid) main();
}
}  // namespace config
#line 2 "Library/option.hpp"
#ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #pragma GCC target("avx,avx2")
    #pragma GCC optimize("unroll-loops")
#endif
#line 2 "Library/utils/binary_search.hpp"
#if __cplusplus >= 201703L
#include <cassert>
#include <cmath>
#include <vector>
namespace workspace {
// binary search on a discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, iter_type>, bool>,
    iter_type>
binary_search(iter_type ok, iter_type ng, pred_type pred) {
  assert(ok != ng);
  std::make_signed_t<decltype(ng - ok)> dist(ng - ok);
  while (1 < dist || dist < -1) {
    iter_type mid(ok + dist / 2);
    if (pred(mid))
      ok = mid, dist -= dist / 2;
    else
      ng = mid, dist /= 2;
  }
  return ok;
}
// parallel binary search on each discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<iter_type>>,
                     std::vector<bool>>,
                 std::vector<iter_type>>
binary_search(std::vector<std::pair<iter_type, iter_type>> ends,
              pred_type pred) {
  std::vector<iter_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      iter_type mid(ok + (ng - ok) / 2);
      if (mids[i] != mid) {
        all_found = false;
        mids[i] = mid;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
// binary search on a real number interval.
template <class real_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, real_type>, bool>,
    real_type>
binary_search(real_type ok, real_type ng, const real_type eps, pred_type pred) {
  assert(ok != ng);
  while (ok + eps < ng || ng + eps < ok) {
    real_type mid{(ok + ng) / 2};
    (pred(mid) ? ok : ng) = mid;
  }
  return ok;
}
// parallel binary search on each real interval.
template <class real_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<real_type>>,
                     std::vector<bool>>,
                 std::vector<real_type>>
binary_search(std::vector<std::pair<real_type, real_type>> ends,
              const real_type eps, pred_type pred) {
  std::vector<real_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      if (ok + eps < ng || ng + eps < ok) {
        all_found = false;
        mids[i] = (ok + ng) / 2;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
}  // namespace workspace
#endif
#line 3 "Library/utils/casefmt.hpp"
namespace workspace {
std::ostream &casefmt(std::ostream& os) { return os << "Case #" << config::caseid << ": "; }
} // namespace workspace
#line 3 "Library/utils/chval.hpp"
namespace workspace {
template <class T, class Comp = std::less<T>>
bool chle(T &x, const T &y, Comp comp = Comp()) {
  return comp(y, x) ? x = y, true : false;
}
template <class T, class Comp = std::less<T>>
bool chge(T &x, const T &y, Comp comp = Comp()) {
  return comp(x, y) ? x = y, true : false;
}
}  // namespace workspace
#line 5 "Library/utils/coordinate_compression.hpp"

template <class T> class coordinate_compression {
  std::vector<T> uniquely;
  std::vector<size_t> compressed;

 public:
  coordinate_compression(const std::vector<T> &raw)
      : uniquely(raw), compressed(raw.size()) {
    std::sort(uniquely.begin(), uniquely.end());
    uniquely.erase(std::unique(uniquely.begin(), uniquely.end()),
                   uniquely.end());
    for (size_t i = 0; i != size(); ++i)
      compressed[i] =
          std::lower_bound(uniquely.begin(), uniquely.end(), raw[i]) -
          uniquely.begin();
  }

  size_t operator[](const size_t idx) const {
    assert(idx < size());
    return compressed[idx];
  }

  size_t size() const { return compressed.size(); }

  size_t count() const { return uniquely.size(); }

  T value(const size_t ord) const {
    assert(ord < count());
    return uniquely[ord];
  }

  size_t order(const T &value) const {
    return std::lower_bound(uniquely.begin(), uniquely.end(), value) -
           uniquely.begin();
  }

  auto begin() { return compressed.begin(); }
  auto end() { return compressed.end(); }
  auto rbegin() { return compressed.rbegin(); }
  auto rend() { return compressed.rend(); }
};
#line 3 "Library/utils/fixed_point.hpp"
namespace workspace {
// specify the return type of lambda.
template <class lambda_type> class fixed_point {
  lambda_type func;

 public:
  fixed_point(lambda_type &&f) : func(std::move(f)) {}
  template <class... Args> auto operator()(Args &&... args) const {
    return func(*this, std::forward<Args>(args)...);
  }
};
}  // namespace workspace
#line 6 "Library/utils/hash.hpp"

#line 3 "Library/utils/sfinae.hpp"
#include <type_traits>

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class T, class = int> struct mapped_of {
  using type = element_type<T>;
};
template <class T>
struct mapped_of<T,
                 typename std::pair<int, typename T::mapped_type>::first_type> {
  using type = typename T::mapped_type;
};
template <class T> using mapped_type = typename mapped_of<T>::type;

template <class T, class = void> struct is_integral_ext : std::false_type {};
template <class T>
struct is_integral_ext<
    T, typename std::enable_if<std::is_integral<T>::value>::type>
    : std::true_type {};
template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};
#if __cplusplus >= 201402
template <class T>
constexpr static bool is_integral_ext_v = is_integral_ext<T>::value;
#endif

template <typename T, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(2 < sizeof(T))>::type> {
  using type = uint_least64_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(4 < sizeof(T))>::type> {
  using type = __uint128_t;
};
#line 8 "Library/utils/hash.hpp"
namespace workspace {
template <class T, class = void> struct hash : std::hash<T> {};
#if __cplusplus >= 201703L
template <class Unique_bits_type>
struct hash<Unique_bits_type,
            enable_if_trait_type<Unique_bits_type,
                                 std::has_unique_object_representations>> {
  size_t operator()(uint64_t x) const {
    static const uint64_t m = std::random_device{}();
    x ^= x >> 23;
    x ^= m;
    x ^= x >> 47;
    return x - (x >> 32);
  }
};
#endif
template <class Key> size_t hash_combine(const size_t &seed, const Key &key) {
  return seed ^
         (hash<Key>()(key) + 0x9e3779b9 /* + (seed << 6) + (seed >> 2) */);
}
template <class T1, class T2> struct hash<std::pair<T1, T2>> {
  size_t operator()(const std::pair<T1, T2> &pair) const {
    return hash_combine(hash<T1>()(pair.first), pair.second);
  }
};
template <class... T> class hash<std::tuple<T...>> {
  template <class Tuple, size_t index = std::tuple_size<Tuple>::value - 1>
  struct tuple_hash {
    static uint64_t apply(const Tuple &t) {
      return hash_combine(tuple_hash<Tuple, index - 1>::apply(t),
                          std::get<index>(t));
    }
  };
  template <class Tuple> struct tuple_hash<Tuple, size_t(-1)> {
    static uint64_t apply(const Tuple &t) { return 0; }
  };

 public:
  uint64_t operator()(const std::tuple<T...> &t) const {
    return tuple_hash<std::tuple<T...>>::apply(t);
  }
};
template <class hash_table> struct hash_table_wrapper : hash_table {
  using key_type = typename hash_table::key_type;
  size_t count(const key_type &key) const {
    return hash_table::find(key) != hash_table::end();
  }
  template <class... Args> auto emplace(Args &&... args) {
    return hash_table::insert(typename hash_table::value_type(args...));
  }
};
template <class Key, class Mapped = __gnu_pbds::null_type>
using cc_hash_table =
    hash_table_wrapper<__gnu_pbds::cc_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped = __gnu_pbds::null_type>
using gp_hash_table =
    hash_table_wrapper<__gnu_pbds::gp_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped>
using unordered_map = std::unordered_map<Key, Mapped, hash<Key>>;
template <class Key> using unordered_set = std::unordered_set<Key, hash<Key>>;
}  // namespace workspace
#line 2 "Library/utils/make_vector.hpp"
#if __cplusplus >= 201703L
#include <vector>
namespace workspace {
template <typename T, size_t N>
constexpr auto make_vector(size_t* sizes, T const& init = T()) {
  if constexpr (N)
    return std::vector(*sizes, make_vector<T, N - 1>(std::next(sizes), init));
  else
    return init;
}
template <typename T, size_t N>
constexpr auto make_vector(const size_t (&sizes)[N], T const& init = T()) {
  return make_vector<T, N>((size_t*)sizes, init);
}
}  // namespace workspace
#endif
#line 3 "Library/utils/random_number_generator.hpp"
template <typename num_type> class random_number_generator {
  typename std::conditional<std::is_integral<num_type>::value,
                            std::uniform_int_distribution<num_type>,
                            std::uniform_real_distribution<num_type>>::type
      unif;

  std::mt19937 engine;

 public:
  random_number_generator(num_type min = std::numeric_limits<num_type>::min(),
                          num_type max = std::numeric_limits<num_type>::max())
      : unif(min, max), engine(std::random_device{}()) {}

  num_type min() const { return unif.min(); }

  num_type max() const { return unif.max(); }

  // generate a random number in [min(), max()].
  num_type operator()() { return unif(engine); }
};
#line 3 "Library/utils/read.hpp"
namespace workspace {
// read with std::cin.
template <class T = void>
struct read
{
    typename std::remove_const<T>::type value;
    template <class... types>
    read(types... args) : value(args...) { std::cin >> value; }
    operator T() const { return value; }
};
template <>
struct read<void>
{
    template <class T>
    operator T() const { T value; std::cin >> value; return value; }
};
} // namespace workspace
#line 4 "Library/utils/stream.hpp"

#line 6 "Library/utils/stream.hpp"
namespace std {
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ' ' << p.second;
}
template <class tuple_t, size_t index> struct tuple_is {
  static istream &apply(istream &is, tuple_t &t) {
    tuple_is<tuple_t, index - 1>::apply(is, t);
    return is >> get<index>(t);
  }
};
template <class tuple_t> struct tuple_is<tuple_t, SIZE_MAX> {
  static istream &apply(istream &is, tuple_t &t) { return is; }
};
template <class... T> istream &operator>>(istream &is, tuple<T...> &t) {
  return tuple_is<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is,
                                                                          t);
}
template <class tuple_t, size_t index> struct tuple_os {
  static ostream &apply(ostream &os, const tuple_t &t) {
    tuple_os<tuple_t, index - 1>::apply(os, t);
    return os << ' ' << get<index>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, 0> {
  static ostream &apply(ostream &os, const tuple_t &t) {
    return os << get<0>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, SIZE_MAX> {
  static ostream &apply(ostream &os, const tuple_t &t) { return os; }
};
template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) {
  return tuple_os<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os,
                                                                          t);
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   istream &>::type
operator>>(istream &is, Container &cont) {
  for (auto &&e : cont) is >> e;
  return is;
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   ostream &>::type
operator<<(ostream &os, const Container &cont) {
  bool head = true;
  for (auto &&e : cont) head ? head = 0 : (os << ' ', 0), os << e;
  return os;
}
}  // namespace std
#line 4 "Library/utils/trinary_search.hpp"
// trinary search on discrete range.
template <class iter_type, class comp_type>
iter_type trinary(iter_type first, iter_type last, comp_type comp)
{
    assert(first < last);
    intmax_t dist(last - first);
    while(dist > 2)
    {
        iter_type left(first + dist / 3), right(first + dist * 2 / 3);
        if(comp(left, right)) last = right, dist = dist * 2 / 3;
        else first = left, dist -= dist / 3;
    }
    if(dist > 1 && comp(first + 1, first)) ++first;
    return first;
}
// trinary search on real numbers.
template <class comp_type>
long double trinary(long double first, long double last, const long double eps, comp_type comp)
{
    assert(first < last);
    while(last - first > eps)
    {
        long double left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
        if(comp(left, right)) last = right;
        else first = left;
    }
    return first;
}
#line 2 "Library/utils/wrapper.hpp"
template <class Container> class reversed {
  Container &ref, copy;

 public:
  reversed(Container &ref) : ref(ref) {}
  reversed(Container &&ref = Container()) : ref(copy), copy(ref) {}
  auto begin() const { return ref.rbegin(); }
  auto end() const { return ref.rend(); }
};
#line 9 "other/h.cpp"

namespace workspace {
void main();
}
int main() { config::loop(workspace::main); }

unsigned config::cases() {
  // return -1; // unspecified
  // int t; std::cin >> t; return t; // given
  return 1;
}

#line 4 "Library/graph/directed/flow/min_cost_flow.hpp"

#line 4 "Library/graph/directed/flow/base.hpp"
// the base class of flow algorithms.
template <class cap_t, class cost_t> struct flow_base {
  struct edge_t {
    size_t src, dst;
    cap_t cap;
    cost_t cost;
    edge_t *rev;
    edge_t() = default;
    edge_t(size_t src, size_t dst, const cap_t &cap, edge_t *rev)
        : src(src), dst(dst), cap(cap), rev(rev) {}
    edge_t(size_t src, size_t dst, const cap_t &cap, const cost_t &cost,
           edge_t *rev)
        : src(src), dst(dst), cap(cap), cost(cost), rev(rev) {}
    const cap_t &flow(const cap_t &f = 0) { return cap -= f, rev->cap += f; }
    bool avbl() const { return static_cast<cap_t>(0) < cap; }
  };  // class edge_t

  class adj_type {
    edge_t *fst, *lst, *clst;

   public:
    template <class... Args> edge_t *emplace(Args &&... args) {
      if (lst == clst) {
        size_t len(clst - fst);
        edge_t *nfst = lst = new edge_t[len << 1];
        for (edge_t *p{fst}; p != clst; ++p, ++lst)
          p->rev->rev = lst, *lst = *p;
        delete[] fst;
        fst = nfst;
        clst = lst + len;
      }
      *lst = edge_t(args...);
      return lst++;
    }
    adj_type() : fst(new edge_t[1]), lst(fst), clst(fst + 1) {}
    ~adj_type() { delete[] fst; }
    edge_t &operator[](size_t i) {
      assert(i < size());
      return *(fst + i);
    }
    size_t size() const { return lst - fst; }
    edge_t *begin() const { return fst; }
    edge_t *end() const { return lst; }
  };  // class adj_type

  flow_base(size_t n = 0) : adjs(n) {}

  flow_base(const flow_base &other) : adjs(other.size()) {
    for (size_t node{}; node != size(); ++node)
      for (const auto &[src, dst, cap, cost, rev] : other[node])
        if (src == node) {
          edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
          ptr->rev = adjs[dst].emplace(dst, src, rev->cap, -cost, ptr);
          rev->src = nil;
        } else {
          rev->rev->src = node;
        }
  }

  flow_base &operator=(const flow_base &rhs) {
    if (this != &rhs) adjs.swap(flow_base(rhs).adjs);
    return *this;
  }

  size_t size() const { return adjs.size(); }

  adj_type &operator[](size_t node) {
    assert(node < size());
    return adjs[node];
  }
  const adj_type &operator[](size_t node) const {
    assert(node < size());
    return adjs[node];
  }

  virtual edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                           const cost_t &cost) {
    assert(src < size());
    assert(dst < size());
    assert(!(cap < static_cast<cap_t>(0)));
    if (!(static_cast<cap_t>(0) < cap) || src == dst) return nullptr;
    edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
    ptr->rev = adjs[dst].emplace(dst, src, 0, -cost, ptr);
    return ptr;
  }

 protected:
  constexpr static size_t nil = -1;
  std::vector<adj_type> adjs;
};  // class flow_base
#line 6 "Library/graph/directed/flow/min_cost_flow.hpp"
// Successive shortest paths algorithm.
template <class cap_t, class cost_t, bool density_tag = false>
class min_cost_flow : public flow_base<cap_t, cost_t> {
  using base = flow_base<cap_t, cost_t>;
  using edge_t = typename base::edge_t;
  using base::adjs;
  using base::nil;

  cost_t min_cost, total_cost;
  std::vector<cap_t> supp;
  std::vector<cost_t> ptnl;

  void copy_member(const min_cost_flow &other) {
    min_cost = other.min_cost;
    total_cost = other.total_cost;
    supp = other.supp;
    ptnl = other.ptnl;
  }

  void Dijkstra(std::vector<edge_t *> &last) {
    const cost_t infty(total_cost + 1);
    std::vector<cost_t> nptnl(size(), infty);
    if constexpr (density_tag) {
      // O(V^2)
      std::vector<bool> used(size());
      for (size_t src{}; src != size(); ++src) {
        if (static_cast<cap_t>(0) < supp[src]) {
          used[src] = true;
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (static_cast<cap_t>(0) < supp[e.dst]) continue;
            if (e.avbl() && e.cost < nptnl[e.dst]) {
              nptnl[e.dst] = e.cost;
              last[e.dst] = &e;
            }
          }
        }
      }
      for (;;) {
        size_t src{nil};
        cost_t sp{infty};
        for (size_t node{}; node != size(); ++node) {
          if (used[node] || nptnl[node] == infty) continue;
          cost_t dist{nptnl[node] - ptnl[node]};
          if (dist < sp) {
            sp = dist;
            src = node;
          }
        }
        if (src == nil) break;
        used[src] = true;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[src] + e.cost < nptnl[e.dst]) {
            nptnl[e.dst] = nptnl[src] + e.cost;
            last[e.dst] = &e;
          }
        }
      }
    } else {
      // O((V + E)logV)
      struct node_t {
        size_t id;
        cost_t dist;
        node_t(size_t id, cost_t dist) : id(id), dist(dist) {}
        bool operator<(const node_t &rhs) const { return rhs.dist < dist; }
      };
      std::priority_queue<node_t> que;
      for (size_t src{}; src != size(); ++src) {
        if (supp[src] > static_cast<cap_t>(0)) {
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (supp[e.dst] > static_cast<cap_t>(0)) continue;
            if (e.avbl() && nptnl[e.dst] > e.cost) {
              que.emplace(e.dst, (nptnl[e.dst] = e.cost) - ptnl[e.dst]);
              last[e.dst] = &e;
            }
          }
        }
      }
      while (!que.empty()) {
        auto [src, ndist] = que.top();
        que.pop();
        if (ndist + ptnl[src] != nptnl[src]) continue;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[e.dst] > nptnl[src] + e.cost) {
            que.emplace(e.dst,
                        (nptnl[e.dst] = nptnl[src] + e.cost) - ptnl[e.dst]);
            last[e.dst] = &e;
          }
        }
      }
    }
    ptnl.swap(nptnl);
  }

 public:
  using base::size;

  min_cost_flow(size_t n = 0)
      : base::flow_base(n), min_cost(0), total_cost(0), supp(n), ptnl(n) {}

  min_cost_flow(const min_cost_flow &other) : base::flow_base(other) {
    copy_member(other);
  }

  min_cost_flow &operator=(const min_cost_flow &other) {
    base::operator=(other);
    copy_member(other);
    return *this;
  }

  edge_t *add_edge(size_t src, size_t dst, const cost_t &cost);

  edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                   const cost_t &cost) override {
    assert(src != dst);
    if (cost < static_cast<cost_t>(0)) {
      supp[src] -= cap;
      supp[dst] += cap;
      min_cost += cap * cost;
      total_cost -= cap * cost;
      return base::add_edge(dst, src, cap, -cost);
    }
    total_cost += cap * cost;
    return base::add_edge(src, dst, cap, cost);
  }

  edge_t *add_edge(size_t src, size_t dst, const cap_t &lower,
                   const cap_t &upper, const cost_t &cost) {
    assert(!(upper < lower));
    supp[src] -= lower;
    supp[dst] += lower;
    min_cost += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  const cap_t &supply(size_t node, const cap_t &vol = 0) {
    assert(node < size());
    return supp[node] += vol;
  }

  const cap_t &demand(size_t node, const cap_t &vol) {
    return supply(node, -vol);
  }

  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge_t *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_t dst{}; dst != size(); ++dst) {
        if (supp[dst] < static_cast<cap_t>(0) and last[dst]) {
          cap_t resid{-supp[dst]};
          size_t src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < supp[src])) {
              resid = supp[src];
              block = src;
            }
            for (edge_t *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            supp[src] -= resid;
            supp[dst] += resid;
            min_cost += ptnl[dst] * resid;
            aug = true;
          }
          if (~block) {
            for (size_t node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
          }
        }
      }
    }
    return std::none_of(begin(supp), end(supp),
                        [](const cap_t &s) { return s < 0 || 0 < s; });
  }

  cost_t optimal() {
    assert(flow());
    return min_cost;
  }
};  // class min_cost_flow
#line 22 "other/h.cpp"

namespace workspace {
void main() {
  // start here!
  const i64 inf = 1e11;
  int n, m, x;
  cin >> n >> m >> x;

  min_cost_flow<i64, i64> base(n * 3);
  // make
  {
    for (int i = 0; i < n; i++) {
      int a, b, p;
      cin >> a >> b >> p;
      base.add_edge(3 * i + 1, 3 * i, inf, p);
      base.add_edge(3 * i, 3 * i + 1, inf, -1);
      base.add_edge(3 * i + 1, 3 * i + 2, inf, 0);
      if (i) base.add_edge(3 * (i - 1), 3 * i, inf, 0);
      base.supply(3 * i, -a);
      base.supply(3 * i + 1, a - b);
      base.supply(3 * i + 2, b);
    }
  }
  for (auto j = 0; j < m; ++j) {
    int u, v, f;
    cin >> u >> v >> f;
    --u, --v;
    if (f > 0) {
      base.add_edge(3 * v, 3 * u + 2, inf, 1);
    } else {
      base.add_edge(3 * u + 2, 3 * v, inf, 0);
    }
  }

  auto ok = [&](int t) -> bool {
    auto mcf = base;
    for (int i = 0; i < n; i++) {
      mcf.add_edge(3 * i + 2, 0, inf, t);
    }
    if (mcf.flow()) {
      auto opt = mcf.optimal();
      return opt >= x;
    }
    return false;
  };

  auto ans = binary_search(x + 100 * n + 1, -1, ok);
  if (ans > x + 100 * n)
    cout << "-1\n";
  else
    cout << ans << eol;
}
}
accuracy: 0.4222222222222222
time_ms: 20
memory_kb: 3664
final_rank: 16

code_snippet: #line 1 "other/h.cpp"
#include <bits/extc++.h>
#if __has_include(<bit>)
#include <bit>
#endif
#line 7 "Library/alias.hpp"
namespace workspace {
constexpr char eol = '\n';
using namespace std;
using i32 = int_least32_t;
using i64 = int_least64_t;
using i128 = __int128_t;
using u32 = uint_least32_t;
using u64 = uint_least64_t;
using u128 = __uint128_t;
template <class T, class Comp = less<T>>
using priority_queue = std::priority_queue<T, vector<T>, Comp>;
template <class T> using stack = std::stack<T, vector<T>>;
}  // namespace workspace
#line 5 "Library/config.hpp"
namespace config {
const auto start_time{std::chrono::system_clock::now()};
int64_t elapsed() {
  using namespace std::chrono;
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - start_time).count();
}
__attribute__((constructor)) void setup() {
  using namespace std;
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(15);
#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (cin >> bufc)
      cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}
unsigned cases(), caseid = 1;
template <class F> void loop(F main) {
  for (const unsigned total = cases(); caseid <= total; ++caseid) main();
}
}  // namespace config
#line 2 "Library/option.hpp"
#ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #pragma GCC target("avx,avx2")
    #pragma GCC optimize("unroll-loops")
#endif
#line 2 "Library/utils/binary_search.hpp"
#if __cplusplus >= 201703L
#include <cassert>
#include <cmath>
#include <vector>
namespace workspace {
// binary search on a discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, iter_type>, bool>,
    iter_type>
binary_search(iter_type ok, iter_type ng, pred_type pred) {
  assert(ok != ng);
  std::make_signed_t<decltype(ng - ok)> dist(ng - ok);
  while (1 < dist || dist < -1) {
    iter_type mid(ok + dist / 2);
    if (pred(mid))
      ok = mid, dist -= dist / 2;
    else
      ng = mid, dist /= 2;
  }
  return ok;
}
// parallel binary search on each discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<iter_type>>,
                     std::vector<bool>>,
                 std::vector<iter_type>>
binary_search(std::vector<std::pair<iter_type, iter_type>> ends,
              pred_type pred) {
  std::vector<iter_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      iter_type mid(ok + (ng - ok) / 2);
      if (mids[i] != mid) {
        all_found = false;
        mids[i] = mid;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
// binary search on a real number interval.
template <class real_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, real_type>, bool>,
    real_type>
binary_search(real_type ok, real_type ng, const real_type eps, pred_type pred) {
  assert(ok != ng);
  while (ok + eps < ng || ng + eps < ok) {
    real_type mid{(ok + ng) / 2};
    (pred(mid) ? ok : ng) = mid;
  }
  return ok;
}
// parallel binary search on each real interval.
template <class real_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<real_type>>,
                     std::vector<bool>>,
                 std::vector<real_type>>
binary_search(std::vector<std::pair<real_type, real_type>> ends,
              const real_type eps, pred_type pred) {
  std::vector<real_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      if (ok + eps < ng || ng + eps < ok) {
        all_found = false;
        mids[i] = (ok + ng) / 2;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
}  // namespace workspace
#endif
#line 3 "Library/utils/casefmt.hpp"
namespace workspace {
std::ostream &casefmt(std::ostream& os) { return os << "Case #" << config::caseid << ": "; }
} // namespace workspace
#line 3 "Library/utils/chval.hpp"
namespace workspace {
template <class T, class Comp = std::less<T>>
bool chle(T &x, const T &y, Comp comp = Comp()) {
  return comp(y, x) ? x = y, true : false;
}
template <class T, class Comp = std::less<T>>
bool chge(T &x, const T &y, Comp comp = Comp()) {
  return comp(x, y) ? x = y, true : false;
}
}  // namespace workspace
#line 5 "Library/utils/coordinate_compression.hpp"

template <class T> class coordinate_compression {
  std::vector<T> uniquely;
  std::vector<size_t> compressed;

 public:
  coordinate_compression(const std::vector<T> &raw)
      : uniquely(raw), compressed(raw.size()) {
    std::sort(uniquely.begin(), uniquely.end());
    uniquely.erase(std::unique(uniquely.begin(), uniquely.end()),
                   uniquely.end());
    for (size_t i = 0; i != size(); ++i)
      compressed[i] =
          std::lower_bound(uniquely.begin(), uniquely.end(), raw[i]) -
          uniquely.begin();
  }

  size_t operator[](const size_t idx) const {
    assert(idx < size());
    return compressed[idx];
  }

  size_t size() const { return compressed.size(); }

  size_t count() const { return uniquely.size(); }

  T value(const size_t ord) const {
    assert(ord < count());
    return uniquely[ord];
  }

  size_t order(const T &value) const {
    return std::lower_bound(uniquely.begin(), uniquely.end(), value) -
           uniquely.begin();
  }

  auto begin() { return compressed.begin(); }
  auto end() { return compressed.end(); }
  auto rbegin() { return compressed.rbegin(); }
  auto rend() { return compressed.rend(); }
};
#line 3 "Library/utils/fixed_point.hpp"
namespace workspace {
// specify the return type of lambda.
template <class lambda_type> class fixed_point {
  lambda_type func;

 public:
  fixed_point(lambda_type &&f) : func(std::move(f)) {}
  template <class... Args> auto operator()(Args &&... args) const {
    return func(*this, std::forward<Args>(args)...);
  }
};
}  // namespace workspace
#line 6 "Library/utils/hash.hpp"

#line 3 "Library/utils/sfinae.hpp"
#include <type_traits>

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class T, class = int> struct mapped_of {
  using type = element_type<T>;
};
template <class T>
struct mapped_of<T,
                 typename std::pair<int, typename T::mapped_type>::first_type> {
  using type = typename T::mapped_type;
};
template <class T> using mapped_type = typename mapped_of<T>::type;

template <class T, class = void> struct is_integral_ext : std::false_type {};
template <class T>
struct is_integral_ext<
    T, typename std::enable_if<std::is_integral<T>::value>::type>
    : std::true_type {};
template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};
#if __cplusplus >= 201402
template <class T>
constexpr static bool is_integral_ext_v = is_integral_ext<T>::value;
#endif

template <typename T, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(2 < sizeof(T))>::type> {
  using type = uint_least64_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(4 < sizeof(T))>::type> {
  using type = __uint128_t;
};
#line 8 "Library/utils/hash.hpp"
namespace workspace {
template <class T, class = void> struct hash : std::hash<T> {};
#if __cplusplus >= 201703L
template <class Unique_bits_type>
struct hash<Unique_bits_type,
            enable_if_trait_type<Unique_bits_type,
                                 std::has_unique_object_representations>> {
  size_t operator()(uint64_t x) const {
    static const uint64_t m = std::random_device{}();
    x ^= x >> 23;
    x ^= m;
    x ^= x >> 47;
    return x - (x >> 32);
  }
};
#endif
template <class Key> size_t hash_combine(const size_t &seed, const Key &key) {
  return seed ^
         (hash<Key>()(key) + 0x9e3779b9 /* + (seed << 6) + (seed >> 2) */);
}
template <class T1, class T2> struct hash<std::pair<T1, T2>> {
  size_t operator()(const std::pair<T1, T2> &pair) const {
    return hash_combine(hash<T1>()(pair.first), pair.second);
  }
};
template <class... T> class hash<std::tuple<T...>> {
  template <class Tuple, size_t index = std::tuple_size<Tuple>::value - 1>
  struct tuple_hash {
    static uint64_t apply(const Tuple &t) {
      return hash_combine(tuple_hash<Tuple, index - 1>::apply(t),
                          std::get<index>(t));
    }
  };
  template <class Tuple> struct tuple_hash<Tuple, size_t(-1)> {
    static uint64_t apply(const Tuple &t) { return 0; }
  };

 public:
  uint64_t operator()(const std::tuple<T...> &t) const {
    return tuple_hash<std::tuple<T...>>::apply(t);
  }
};
template <class hash_table> struct hash_table_wrapper : hash_table {
  using key_type = typename hash_table::key_type;
  size_t count(const key_type &key) const {
    return hash_table::find(key) != hash_table::end();
  }
  template <class... Args> auto emplace(Args &&... args) {
    return hash_table::insert(typename hash_table::value_type(args...));
  }
};
template <class Key, class Mapped = __gnu_pbds::null_type>
using cc_hash_table =
    hash_table_wrapper<__gnu_pbds::cc_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped = __gnu_pbds::null_type>
using gp_hash_table =
    hash_table_wrapper<__gnu_pbds::gp_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped>
using unordered_map = std::unordered_map<Key, Mapped, hash<Key>>;
template <class Key> using unordered_set = std::unordered_set<Key, hash<Key>>;
}  // namespace workspace
#line 2 "Library/utils/make_vector.hpp"
#if __cplusplus >= 201703L
#include <vector>
namespace workspace {
template <typename T, size_t N>
constexpr auto make_vector(size_t* sizes, T const& init = T()) {
  if constexpr (N)
    return std::vector(*sizes, make_vector<T, N - 1>(std::next(sizes), init));
  else
    return init;
}
template <typename T, size_t N>
constexpr auto make_vector(const size_t (&sizes)[N], T const& init = T()) {
  return make_vector<T, N>((size_t*)sizes, init);
}
}  // namespace workspace
#endif
#line 3 "Library/utils/random_number_generator.hpp"
template <typename num_type> class random_number_generator {
  typename std::conditional<std::is_integral<num_type>::value,
                            std::uniform_int_distribution<num_type>,
                            std::uniform_real_distribution<num_type>>::type
      unif;

  std::mt19937 engine;

 public:
  random_number_generator(num_type min = std::numeric_limits<num_type>::min(),
                          num_type max = std::numeric_limits<num_type>::max())
      : unif(min, max), engine(std::random_device{}()) {}

  num_type min() const { return unif.min(); }

  num_type max() const { return unif.max(); }

  // generate a random number in [min(), max()].
  num_type operator()() { return unif(engine); }
};
#line 3 "Library/utils/read.hpp"
namespace workspace {
// read with std::cin.
template <class T = void>
struct read
{
    typename std::remove_const<T>::type value;
    template <class... types>
    read(types... args) : value(args...) { std::cin >> value; }
    operator T() const { return value; }
};
template <>
struct read<void>
{
    template <class T>
    operator T() const { T value; std::cin >> value; return value; }
};
} // namespace workspace
#line 4 "Library/utils/stream.hpp"

#line 6 "Library/utils/stream.hpp"
namespace std {
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ' ' << p.second;
}
template <class tuple_t, size_t index> struct tuple_is {
  static istream &apply(istream &is, tuple_t &t) {
    tuple_is<tuple_t, index - 1>::apply(is, t);
    return is >> get<index>(t);
  }
};
template <class tuple_t> struct tuple_is<tuple_t, SIZE_MAX> {
  static istream &apply(istream &is, tuple_t &t) { return is; }
};
template <class... T> istream &operator>>(istream &is, tuple<T...> &t) {
  return tuple_is<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is,
                                                                          t);
}
template <class tuple_t, size_t index> struct tuple_os {
  static ostream &apply(ostream &os, const tuple_t &t) {
    tuple_os<tuple_t, index - 1>::apply(os, t);
    return os << ' ' << get<index>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, 0> {
  static ostream &apply(ostream &os, const tuple_t &t) {
    return os << get<0>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, SIZE_MAX> {
  static ostream &apply(ostream &os, const tuple_t &t) { return os; }
};
template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) {
  return tuple_os<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os,
                                                                          t);
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   istream &>::type
operator>>(istream &is, Container &cont) {
  for (auto &&e : cont) is >> e;
  return is;
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   ostream &>::type
operator<<(ostream &os, const Container &cont) {
  bool head = true;
  for (auto &&e : cont) head ? head = 0 : (os << ' ', 0), os << e;
  return os;
}
}  // namespace std
#line 4 "Library/utils/trinary_search.hpp"
// trinary search on discrete range.
template <class iter_type, class comp_type>
iter_type trinary(iter_type first, iter_type last, comp_type comp)
{
    assert(first < last);
    intmax_t dist(last - first);
    while(dist > 2)
    {
        iter_type left(first + dist / 3), right(first + dist * 2 / 3);
        if(comp(left, right)) last = right, dist = dist * 2 / 3;
        else first = left, dist -= dist / 3;
    }
    if(dist > 1 && comp(first + 1, first)) ++first;
    return first;
}
// trinary search on real numbers.
template <class comp_type>
long double trinary(long double first, long double last, const long double eps, comp_type comp)
{
    assert(first < last);
    while(last - first > eps)
    {
        long double left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
        if(comp(left, right)) last = right;
        else first = left;
    }
    return first;
}
#line 2 "Library/utils/wrapper.hpp"
template <class Container> class reversed {
  Container &ref, copy;

 public:
  reversed(Container &ref) : ref(ref) {}
  reversed(Container &&ref = Container()) : ref(copy), copy(ref) {}
  auto begin() const { return ref.rbegin(); }
  auto end() const { return ref.rend(); }
};
#line 9 "other/h.cpp"

namespace workspace {
void main();
}
int main() { config::loop(workspace::main); }

unsigned config::cases() {
  // return -1; // unspecified
  // int t; std::cin >> t; return t; // given
  return 1;
}

#line 4 "Library/graph/directed/flow/min_cost_flow.hpp"

#line 4 "Library/graph/directed/flow/base.hpp"
// the base class of flow algorithms.
template <class cap_t, class cost_t> struct flow_base {
  struct edge_t {
    size_t src, dst;
    cap_t cap;
    cost_t cost;
    edge_t *rev;
    edge_t() = default;
    edge_t(size_t src, size_t dst, const cap_t &cap, edge_t *rev)
        : src(src), dst(dst), cap(cap), rev(rev) {}
    edge_t(size_t src, size_t dst, const cap_t &cap, const cost_t &cost,
           edge_t *rev)
        : src(src), dst(dst), cap(cap), cost(cost), rev(rev) {}
    const cap_t &flow(const cap_t &f = 0) { return cap -= f, rev->cap += f; }
    bool avbl() const { return static_cast<cap_t>(0) < cap; }
  };  // class edge_t

  class adj_type {
    edge_t *fst, *lst, *clst;

   public:
    template <class... Args> edge_t *emplace(Args &&... args) {
      if (lst == clst) {
        size_t len(clst - fst);
        edge_t *nfst = lst = new edge_t[len << 1];
        for (edge_t *p{fst}; p != clst; ++p, ++lst)
          p->rev->rev = lst, *lst = *p;
        delete[] fst;
        fst = nfst;
        clst = lst + len;
      }
      *lst = edge_t(args...);
      return lst++;
    }
    adj_type() : fst(new edge_t[1]), lst(fst), clst(fst + 1) {}
    ~adj_type() { delete[] fst; }
    edge_t &operator[](size_t i) {
      assert(i < size());
      return *(fst + i);
    }
    size_t size() const { return lst - fst; }
    edge_t *begin() const { return fst; }
    edge_t *end() const { return lst; }
  };  // class adj_type

  flow_base(size_t n = 0) : adjs(n) {}

  flow_base(const flow_base &other) : adjs(other.size()) {
    for (size_t node{}; node != size(); ++node)
      for (const auto &[src, dst, cap, cost, rev] : other[node])
        if (src == node) {
          edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
          ptr->rev = adjs[dst].emplace(dst, src, rev->cap, -cost, ptr);
          rev->src = nil;
        } else {
          rev->rev->src = node;
        }
  }

  flow_base &operator=(const flow_base &rhs) {
    if (this != &rhs) adjs.swap(flow_base(rhs).adjs);
    return *this;
  }

  size_t size() const { return adjs.size(); }

  adj_type &operator[](size_t node) {
    assert(node < size());
    return adjs[node];
  }
  const adj_type &operator[](size_t node) const {
    assert(node < size());
    return adjs[node];
  }

  virtual edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                           const cost_t &cost) {
    assert(src < size());
    assert(dst < size());
    assert(!(cap < static_cast<cap_t>(0)));
    if (!(static_cast<cap_t>(0) < cap) || src == dst) return nullptr;
    edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
    ptr->rev = adjs[dst].emplace(dst, src, 0, -cost, ptr);
    return ptr;
  }

 protected:
  constexpr static size_t nil = -1;
  std::vector<adj_type> adjs;
};  // class flow_base
#line 6 "Library/graph/directed/flow/min_cost_flow.hpp"
// Successive shortest paths algorithm.
template <class cap_t, class cost_t, bool density_tag = false>
class min_cost_flow : public flow_base<cap_t, cost_t> {
  using base = flow_base<cap_t, cost_t>;
  using edge_t = typename base::edge_t;
  using base::adjs;
  using base::nil;

  cost_t min_cost, total_cost;
  std::vector<cap_t> supp;
  std::vector<cost_t> ptnl;

  void copy_member(const min_cost_flow &other) {
    min_cost = other.min_cost;
    total_cost = other.total_cost;
    supp = other.supp;
    ptnl = other.ptnl;
  }

  void Dijkstra(std::vector<edge_t *> &last) {
    const cost_t infty(total_cost + 1);
    std::vector<cost_t> nptnl(size(), infty);
    if constexpr (density_tag) {
      // O(V^2)
      std::vector<bool> used(size());
      for (size_t src{}; src != size(); ++src) {
        if (static_cast<cap_t>(0) < supp[src]) {
          used[src] = true;
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (static_cast<cap_t>(0) < supp[e.dst]) continue;
            if (e.avbl() && e.cost < nptnl[e.dst]) {
              nptnl[e.dst] = e.cost;
              last[e.dst] = &e;
            }
          }
        }
      }
      for (;;) {
        size_t src{nil};
        cost_t sp{infty};
        for (size_t node{}; node != size(); ++node) {
          if (used[node] || nptnl[node] == infty) continue;
          cost_t dist{nptnl[node] - ptnl[node]};
          if (dist < sp) {
            sp = dist;
            src = node;
          }
        }
        if (src == nil) break;
        used[src] = true;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[src] + e.cost < nptnl[e.dst]) {
            nptnl[e.dst] = nptnl[src] + e.cost;
            last[e.dst] = &e;
          }
        }
      }
    } else {
      // O((V + E)logV)
      struct node_t {
        size_t id;
        cost_t dist;
        node_t(size_t id, cost_t dist) : id(id), dist(dist) {}
        bool operator<(const node_t &rhs) const { return rhs.dist < dist; }
      };
      std::priority_queue<node_t> que;
      for (size_t src{}; src != size(); ++src) {
        if (supp[src] > static_cast<cap_t>(0)) {
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (supp[e.dst] > static_cast<cap_t>(0)) continue;
            if (e.avbl() && nptnl[e.dst] > e.cost) {
              que.emplace(e.dst, (nptnl[e.dst] = e.cost) - ptnl[e.dst]);
              last[e.dst] = &e;
            }
          }
        }
      }
      while (!que.empty()) {
        auto [src, ndist] = que.top();
        que.pop();
        if (ndist + ptnl[src] != nptnl[src]) continue;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[e.dst] > nptnl[src] + e.cost) {
            que.emplace(e.dst,
                        (nptnl[e.dst] = nptnl[src] + e.cost) - ptnl[e.dst]);
            last[e.dst] = &e;
          }
        }
      }
    }
    ptnl.swap(nptnl);
  }

 public:
  using base::size;

  min_cost_flow(size_t n = 0)
      : base::flow_base(n), min_cost(0), total_cost(0), supp(n), ptnl(n) {}

  min_cost_flow(const min_cost_flow &other) : base::flow_base(other) {
    copy_member(other);
  }

  min_cost_flow &operator=(const min_cost_flow &other) {
    base::operator=(other);
    copy_member(other);
    return *this;
  }

  edge_t *add_edge(size_t src, size_t dst, const cost_t &cost);

  edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                   const cost_t &cost) override {
    assert(src != dst);
    if (cost < static_cast<cost_t>(0)) {
      supp[src] -= cap;
      supp[dst] += cap;
      min_cost += cap * cost;
      total_cost -= cap * cost;
      return base::add_edge(dst, src, cap, -cost);
    }
    total_cost += cap * cost;
    return base::add_edge(src, dst, cap, cost);
  }

  edge_t *add_edge(size_t src, size_t dst, const cap_t &lower,
                   const cap_t &upper, const cost_t &cost) {
    assert(!(upper < lower));
    supp[src] -= lower;
    supp[dst] += lower;
    min_cost += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  const cap_t &supply(size_t node, const cap_t &vol = 0) {
    assert(node < size());
    return supp[node] += vol;
  }

  const cap_t &demand(size_t node, const cap_t &vol) {
    return supply(node, -vol);
  }

  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge_t *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_t dst{}; dst != size(); ++dst) {
        if (supp[dst] < static_cast<cap_t>(0) and last[dst]) {
          cap_t resid{-supp[dst]};
          size_t src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < supp[src])) {
              resid = supp[src];
              block = src;
            }
            for (edge_t *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            supp[src] -= resid;
            supp[dst] += resid;
            min_cost += ptnl[dst] * resid;
            aug = true;
          }
          if (~block) {
            for (size_t node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
          }
        }
      }
    }
    return std::none_of(begin(supp), end(supp),
                        [](const cap_t &s) { return s < 0 || 0 < s; });
  }

  cost_t optimal() {
    assert(flow());
    return min_cost;
  }
};  // class min_cost_flow
#line 22 "other/h.cpp"

namespace workspace {
void main() {
  // start here!
  const i64 inf = 1e12;
  int n, m, x;
  cin >> n >> m >> x;

  min_cost_flow<i64, i64> base(n * 3);
  // make
  {
    for (int i = 0; i < n; i++) {
      int a, b, p;
      cin >> a >> b >> p;
      base.add_edge(3 * i + 1, 3 * i, inf, p);
      base.add_edge(3 * i, 3 * i + 1, inf, -1);
      base.add_edge(3 * i + 1, 3 * i + 2, inf, 0);
      if (i) base.add_edge(3 * (i - 1), 3 * i, inf, 0);
      base.supply(3 * i, -a);
      base.supply(3 * i + 1, a - b);
      base.supply(3 * i + 2, b);
    }
  }
  for (auto j = 0; j < m; ++j) {
    int u, v, f;
    cin >> u >> v >> f;
    --u, --v;
    if (f > 0) {
      base.add_edge(3 * v, 3 * u + 2, inf, 1);
    } else {
      base.add_edge(3 * u + 2, 3 * v, inf, 0);
    }
  }

  auto ok = [&](int t) -> bool {
    auto mcf = base;
    for (int i = 0; i < n; i++) {
      mcf.add_edge(3 * i + 2, 0, inf, t);
    }
    if (mcf.flow()) {
      auto opt = mcf.optimal();
      return opt >= x;
    }
    return false;
  };

  auto ans = binary_search(x + 100 * n + 1, -1, ok);
  if (ans > x + 100 * n)
    cout << "-1\n";
  else
    cout << ans << eol;
}
}
accuracy: 0.4222222222222222
time_ms: 20
memory_kb: 3592
final_rank: 12

code_snippet: #line 1 "other/h.cpp"
#include <bits/extc++.h>
#if __has_include(<bit>)
#include <bit>
#endif
#line 7 "Library/alias.hpp"
namespace workspace {
constexpr char eol = '\n';
using namespace std;
using i32 = int_least32_t;
using i64 = int_least64_t;
using i128 = __int128_t;
using u32 = uint_least32_t;
using u64 = uint_least64_t;
using u128 = __uint128_t;
template <class T, class Comp = less<T>>
using priority_queue = std::priority_queue<T, vector<T>, Comp>;
template <class T> using stack = std::stack<T, vector<T>>;
}  // namespace workspace
#line 5 "Library/config.hpp"
namespace config {
const auto start_time{std::chrono::system_clock::now()};
int64_t elapsed() {
  using namespace std::chrono;
  const auto end_time{system_clock::now()};
  return duration_cast<milliseconds>(end_time - start_time).count();
}
__attribute__((constructor)) void setup() {
  using namespace std;
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(15);
#ifdef _buffer_check
  atexit([] {
    char bufc;
    if (cin >> bufc)
      cerr << "\n\033[43m\033[30mwarning: buffer not empty.\033[0m\n\n";
  });
#endif
}
unsigned cases(), caseid = 1;
template <class F> void loop(F main) {
  for (const unsigned total = cases(); caseid <= total; ++caseid) main();
}
}  // namespace config
#line 2 "Library/option.hpp"
#ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #pragma GCC target("avx,avx2")
    #pragma GCC optimize("unroll-loops")
#endif
#line 2 "Library/utils/binary_search.hpp"
#if __cplusplus >= 201703L
#include <cassert>
#include <cmath>
#include <vector>
namespace workspace {
// binary search on a discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, iter_type>, bool>,
    iter_type>
binary_search(iter_type ok, iter_type ng, pred_type pred) {
  assert(ok != ng);
  std::make_signed_t<decltype(ng - ok)> dist(ng - ok);
  while (1 < dist || dist < -1) {
    iter_type mid(ok + dist / 2);
    if (pred(mid))
      ok = mid, dist -= dist / 2;
    else
      ng = mid, dist /= 2;
  }
  return ok;
}
// parallel binary search on each discrete range.
template <class iter_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<iter_type>>,
                     std::vector<bool>>,
                 std::vector<iter_type>>
binary_search(std::vector<std::pair<iter_type, iter_type>> ends,
              pred_type pred) {
  std::vector<iter_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      iter_type mid(ok + (ng - ok) / 2);
      if (mids[i] != mid) {
        all_found = false;
        mids[i] = mid;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
// binary search on a real number interval.
template <class real_type, class pred_type>
std::enable_if_t<
    std::is_convertible_v<std::invoke_result_t<pred_type, real_type>, bool>,
    real_type>
binary_search(real_type ok, real_type ng, const real_type eps, pred_type pred) {
  assert(ok != ng);
  while (ok + eps < ng || ng + eps < ok) {
    real_type mid{(ok + ng) / 2};
    (pred(mid) ? ok : ng) = mid;
  }
  return ok;
}
// parallel binary search on each real interval.
template <class real_type, class pred_type>
std::enable_if_t<std::is_convertible_v<
                     std::invoke_result_t<pred_type, std::vector<real_type>>,
                     std::vector<bool>>,
                 std::vector<real_type>>
binary_search(std::vector<std::pair<real_type, real_type>> ends,
              const real_type eps, pred_type pred) {
  std::vector<real_type> mids(ends.size());
  for (;;) {
    bool all_found = true;
    for (size_t i{}; i != ends.size(); ++i) {
      auto [ok, ng] = ends[i];
      if (ok + eps < ng || ng + eps < ok) {
        all_found = false;
        mids[i] = (ok + ng) / 2;
      }
    }
    if (all_found) break;
    auto res = pred(mids);
    for (size_t i{}; i != ends.size(); ++i) {
      (res[i] ? ends[i].first : ends[i].second) = mids[i];
    }
  }
  return mids;
}
}  // namespace workspace
#endif
#line 3 "Library/utils/casefmt.hpp"
namespace workspace {
std::ostream &casefmt(std::ostream& os) { return os << "Case #" << config::caseid << ": "; }
} // namespace workspace
#line 3 "Library/utils/chval.hpp"
namespace workspace {
template <class T, class Comp = std::less<T>>
bool chle(T &x, const T &y, Comp comp = Comp()) {
  return comp(y, x) ? x = y, true : false;
}
template <class T, class Comp = std::less<T>>
bool chge(T &x, const T &y, Comp comp = Comp()) {
  return comp(x, y) ? x = y, true : false;
}
}  // namespace workspace
#line 5 "Library/utils/coordinate_compression.hpp"

template <class T> class coordinate_compression {
  std::vector<T> uniquely;
  std::vector<size_t> compressed;

 public:
  coordinate_compression(const std::vector<T> &raw)
      : uniquely(raw), compressed(raw.size()) {
    std::sort(uniquely.begin(), uniquely.end());
    uniquely.erase(std::unique(uniquely.begin(), uniquely.end()),
                   uniquely.end());
    for (size_t i = 0; i != size(); ++i)
      compressed[i] =
          std::lower_bound(uniquely.begin(), uniquely.end(), raw[i]) -
          uniquely.begin();
  }

  size_t operator[](const size_t idx) const {
    assert(idx < size());
    return compressed[idx];
  }

  size_t size() const { return compressed.size(); }

  size_t count() const { return uniquely.size(); }

  T value(const size_t ord) const {
    assert(ord < count());
    return uniquely[ord];
  }

  size_t order(const T &value) const {
    return std::lower_bound(uniquely.begin(), uniquely.end(), value) -
           uniquely.begin();
  }

  auto begin() { return compressed.begin(); }
  auto end() { return compressed.end(); }
  auto rbegin() { return compressed.rbegin(); }
  auto rend() { return compressed.rend(); }
};
#line 3 "Library/utils/fixed_point.hpp"
namespace workspace {
// specify the return type of lambda.
template <class lambda_type> class fixed_point {
  lambda_type func;

 public:
  fixed_point(lambda_type &&f) : func(std::move(f)) {}
  template <class... Args> auto operator()(Args &&... args) const {
    return func(*this, std::forward<Args>(args)...);
  }
};
}  // namespace workspace
#line 6 "Library/utils/hash.hpp"

#line 3 "Library/utils/sfinae.hpp"
#include <type_traits>

template <class type, template <class> class trait>
using enable_if_trait_type = typename std::enable_if<trait<type>::value>::type;

template <class Container>
using element_type = typename std::decay<decltype(
    *std::begin(std::declval<Container&>()))>::type;

template <class T, class = int> struct mapped_of {
  using type = element_type<T>;
};
template <class T>
struct mapped_of<T,
                 typename std::pair<int, typename T::mapped_type>::first_type> {
  using type = typename T::mapped_type;
};
template <class T> using mapped_type = typename mapped_of<T>::type;

template <class T, class = void> struct is_integral_ext : std::false_type {};
template <class T>
struct is_integral_ext<
    T, typename std::enable_if<std::is_integral<T>::value>::type>
    : std::true_type {};
template <> struct is_integral_ext<__int128_t> : std::true_type {};
template <> struct is_integral_ext<__uint128_t> : std::true_type {};
#if __cplusplus >= 201402
template <class T>
constexpr static bool is_integral_ext_v = is_integral_ext<T>::value;
#endif

template <typename T, typename = void> struct multiplicable_uint {
  using type = uint_least32_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(2 < sizeof(T))>::type> {
  using type = uint_least64_t;
};
template <typename T>
struct multiplicable_uint<T, typename std::enable_if<(4 < sizeof(T))>::type> {
  using type = __uint128_t;
};
#line 8 "Library/utils/hash.hpp"
namespace workspace {
template <class T, class = void> struct hash : std::hash<T> {};
#if __cplusplus >= 201703L
template <class Unique_bits_type>
struct hash<Unique_bits_type,
            enable_if_trait_type<Unique_bits_type,
                                 std::has_unique_object_representations>> {
  size_t operator()(uint64_t x) const {
    static const uint64_t m = std::random_device{}();
    x ^= x >> 23;
    x ^= m;
    x ^= x >> 47;
    return x - (x >> 32);
  }
};
#endif
template <class Key> size_t hash_combine(const size_t &seed, const Key &key) {
  return seed ^
         (hash<Key>()(key) + 0x9e3779b9 /* + (seed << 6) + (seed >> 2) */);
}
template <class T1, class T2> struct hash<std::pair<T1, T2>> {
  size_t operator()(const std::pair<T1, T2> &pair) const {
    return hash_combine(hash<T1>()(pair.first), pair.second);
  }
};
template <class... T> class hash<std::tuple<T...>> {
  template <class Tuple, size_t index = std::tuple_size<Tuple>::value - 1>
  struct tuple_hash {
    static uint64_t apply(const Tuple &t) {
      return hash_combine(tuple_hash<Tuple, index - 1>::apply(t),
                          std::get<index>(t));
    }
  };
  template <class Tuple> struct tuple_hash<Tuple, size_t(-1)> {
    static uint64_t apply(const Tuple &t) { return 0; }
  };

 public:
  uint64_t operator()(const std::tuple<T...> &t) const {
    return tuple_hash<std::tuple<T...>>::apply(t);
  }
};
template <class hash_table> struct hash_table_wrapper : hash_table {
  using key_type = typename hash_table::key_type;
  size_t count(const key_type &key) const {
    return hash_table::find(key) != hash_table::end();
  }
  template <class... Args> auto emplace(Args &&... args) {
    return hash_table::insert(typename hash_table::value_type(args...));
  }
};
template <class Key, class Mapped = __gnu_pbds::null_type>
using cc_hash_table =
    hash_table_wrapper<__gnu_pbds::cc_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped = __gnu_pbds::null_type>
using gp_hash_table =
    hash_table_wrapper<__gnu_pbds::gp_hash_table<Key, Mapped, hash<Key>>>;
template <class Key, class Mapped>
using unordered_map = std::unordered_map<Key, Mapped, hash<Key>>;
template <class Key> using unordered_set = std::unordered_set<Key, hash<Key>>;
}  // namespace workspace
#line 2 "Library/utils/make_vector.hpp"
#if __cplusplus >= 201703L
#include <vector>
namespace workspace {
template <typename T, size_t N>
constexpr auto make_vector(size_t* sizes, T const& init = T()) {
  if constexpr (N)
    return std::vector(*sizes, make_vector<T, N - 1>(std::next(sizes), init));
  else
    return init;
}
template <typename T, size_t N>
constexpr auto make_vector(const size_t (&sizes)[N], T const& init = T()) {
  return make_vector<T, N>((size_t*)sizes, init);
}
}  // namespace workspace
#endif
#line 3 "Library/utils/random_number_generator.hpp"
template <typename num_type> class random_number_generator {
  typename std::conditional<std::is_integral<num_type>::value,
                            std::uniform_int_distribution<num_type>,
                            std::uniform_real_distribution<num_type>>::type
      unif;

  std::mt19937 engine;

 public:
  random_number_generator(num_type min = std::numeric_limits<num_type>::min(),
                          num_type max = std::numeric_limits<num_type>::max())
      : unif(min, max), engine(std::random_device{}()) {}

  num_type min() const { return unif.min(); }

  num_type max() const { return unif.max(); }

  // generate a random number in [min(), max()].
  num_type operator()() { return unif(engine); }
};
#line 3 "Library/utils/read.hpp"
namespace workspace {
// read with std::cin.
template <class T = void>
struct read
{
    typename std::remove_const<T>::type value;
    template <class... types>
    read(types... args) : value(args...) { std::cin >> value; }
    operator T() const { return value; }
};
template <>
struct read<void>
{
    template <class T>
    operator T() const { T value; std::cin >> value; return value; }
};
} // namespace workspace
#line 4 "Library/utils/stream.hpp"

#line 6 "Library/utils/stream.hpp"
namespace std {
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ' ' << p.second;
}
template <class tuple_t, size_t index> struct tuple_is {
  static istream &apply(istream &is, tuple_t &t) {
    tuple_is<tuple_t, index - 1>::apply(is, t);
    return is >> get<index>(t);
  }
};
template <class tuple_t> struct tuple_is<tuple_t, SIZE_MAX> {
  static istream &apply(istream &is, tuple_t &t) { return is; }
};
template <class... T> istream &operator>>(istream &is, tuple<T...> &t) {
  return tuple_is<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is,
                                                                          t);
}
template <class tuple_t, size_t index> struct tuple_os {
  static ostream &apply(ostream &os, const tuple_t &t) {
    tuple_os<tuple_t, index - 1>::apply(os, t);
    return os << ' ' << get<index>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, 0> {
  static ostream &apply(ostream &os, const tuple_t &t) {
    return os << get<0>(t);
  }
};
template <class tuple_t> struct tuple_os<tuple_t, SIZE_MAX> {
  static ostream &apply(ostream &os, const tuple_t &t) { return os; }
};
template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) {
  return tuple_os<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os,
                                                                          t);
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   istream &>::type
operator>>(istream &is, Container &cont) {
  for (auto &&e : cont) is >> e;
  return is;
}
template <class Container, typename Value = element_type<Container>>
typename enable_if<!is_same<typename decay<Container>::type, string>::value &&
                       !is_same<typename decay<Container>::type, char *>::value,
                   ostream &>::type
operator<<(ostream &os, const Container &cont) {
  bool head = true;
  for (auto &&e : cont) head ? head = 0 : (os << ' ', 0), os << e;
  return os;
}
}  // namespace std
#line 4 "Library/utils/trinary_search.hpp"
// trinary search on discrete range.
template <class iter_type, class comp_type>
iter_type trinary(iter_type first, iter_type last, comp_type comp)
{
    assert(first < last);
    intmax_t dist(last - first);
    while(dist > 2)
    {
        iter_type left(first + dist / 3), right(first + dist * 2 / 3);
        if(comp(left, right)) last = right, dist = dist * 2 / 3;
        else first = left, dist -= dist / 3;
    }
    if(dist > 1 && comp(first + 1, first)) ++first;
    return first;
}
// trinary search on real numbers.
template <class comp_type>
long double trinary(long double first, long double last, const long double eps, comp_type comp)
{
    assert(first < last);
    while(last - first > eps)
    {
        long double left{(first * 2 + last) / 3}, right{(first + last * 2) / 3};
        if(comp(left, right)) last = right;
        else first = left;
    }
    return first;
}
#line 2 "Library/utils/wrapper.hpp"
template <class Container> class reversed {
  Container &ref, copy;

 public:
  reversed(Container &ref) : ref(ref) {}
  reversed(Container &&ref = Container()) : ref(copy), copy(ref) {}
  auto begin() const { return ref.rbegin(); }
  auto end() const { return ref.rend(); }
};
#line 9 "other/h.cpp"

namespace workspace {
void main();
}
int main() { config::loop(workspace::main); }

unsigned config::cases() {
  // return -1; // unspecified
  // int t; std::cin >> t; return t; // given
  return 1;
}

#line 4 "Library/graph/directed/flow/min_cost_flow.hpp"

#line 4 "Library/graph/directed/flow/base.hpp"
// the base class of flow algorithms.
template <class cap_t, class cost_t> struct flow_base {
  struct edge_t {
    size_t src, dst;
    cap_t cap;
    cost_t cost;
    edge_t *rev;
    edge_t() = default;
    edge_t(size_t src, size_t dst, const cap_t &cap, edge_t *rev)
        : src(src), dst(dst), cap(cap), rev(rev) {}
    edge_t(size_t src, size_t dst, const cap_t &cap, const cost_t &cost,
           edge_t *rev)
        : src(src), dst(dst), cap(cap), cost(cost), rev(rev) {}
    const cap_t &flow(const cap_t &f = 0) { return cap -= f, rev->cap += f; }
    bool avbl() const { return static_cast<cap_t>(0) < cap; }
  };  // class edge_t

  class adj_type {
    edge_t *fst, *lst, *clst;

   public:
    template <class... Args> edge_t *emplace(Args &&... args) {
      if (lst == clst) {
        size_t len(clst - fst);
        edge_t *nfst = lst = new edge_t[len << 1];
        for (edge_t *p{fst}; p != clst; ++p, ++lst)
          p->rev->rev = lst, *lst = *p;
        delete[] fst;
        fst = nfst;
        clst = lst + len;
      }
      *lst = edge_t(args...);
      return lst++;
    }
    adj_type() : fst(new edge_t[1]), lst(fst), clst(fst + 1) {}
    ~adj_type() { delete[] fst; }
    edge_t &operator[](size_t i) {
      assert(i < size());
      return *(fst + i);
    }
    size_t size() const { return lst - fst; }
    edge_t *begin() const { return fst; }
    edge_t *end() const { return lst; }
  };  // class adj_type

  flow_base(size_t n = 0) : adjs(n) {}

  flow_base(const flow_base &other) : adjs(other.size()) {
    for (size_t node{}; node != size(); ++node)
      for (const auto &[src, dst, cap, cost, rev] : other[node])
        if (src == node) {
          edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
          ptr->rev = adjs[dst].emplace(dst, src, rev->cap, -cost, ptr);
          rev->src = nil;
        } else {
          rev->rev->src = node;
        }
  }

  flow_base &operator=(const flow_base &rhs) {
    if (this != &rhs) adjs.swap(flow_base(rhs).adjs);
    return *this;
  }

  size_t size() const { return adjs.size(); }

  adj_type &operator[](size_t node) {
    assert(node < size());
    return adjs[node];
  }
  const adj_type &operator[](size_t node) const {
    assert(node < size());
    return adjs[node];
  }

  virtual edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                           const cost_t &cost) {
    assert(src < size());
    assert(dst < size());
    assert(!(cap < static_cast<cap_t>(0)));
    if (!(static_cast<cap_t>(0) < cap) || src == dst) return nullptr;
    edge_t *ptr = adjs[src].emplace(src, dst, cap, cost, nullptr);
    ptr->rev = adjs[dst].emplace(dst, src, 0, -cost, ptr);
    return ptr;
  }

 protected:
  constexpr static size_t nil = -1;
  std::vector<adj_type> adjs;
};  // class flow_base
#line 6 "Library/graph/directed/flow/min_cost_flow.hpp"
// Successive shortest paths algorithm.
template <class cap_t, class cost_t, bool density_tag = false>
class min_cost_flow : public flow_base<cap_t, cost_t> {
  using base = flow_base<cap_t, cost_t>;
  using edge_t = typename base::edge_t;
  using base::adjs;
  using base::nil;

  cost_t min_cost, total_cost;
  std::vector<cap_t> supp;
  std::vector<cost_t> ptnl;

  void copy_member(const min_cost_flow &other) {
    min_cost = other.min_cost;
    total_cost = other.total_cost;
    supp = other.supp;
    ptnl = other.ptnl;
  }

  void Dijkstra(std::vector<edge_t *> &last) {
    const cost_t infty(total_cost + 1);
    std::vector<cost_t> nptnl(size(), infty);
    if constexpr (density_tag) {
      // O(V^2)
      std::vector<bool> used(size());
      for (size_t src{}; src != size(); ++src) {
        if (static_cast<cap_t>(0) < supp[src]) {
          used[src] = true;
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (static_cast<cap_t>(0) < supp[e.dst]) continue;
            if (e.avbl() && e.cost < nptnl[e.dst]) {
              nptnl[e.dst] = e.cost;
              last[e.dst] = &e;
            }
          }
        }
      }
      for (;;) {
        size_t src{nil};
        cost_t sp{infty};
        for (size_t node{}; node != size(); ++node) {
          if (used[node] || nptnl[node] == infty) continue;
          cost_t dist{nptnl[node] - ptnl[node]};
          if (dist < sp) {
            sp = dist;
            src = node;
          }
        }
        if (src == nil) break;
        used[src] = true;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[src] + e.cost < nptnl[e.dst]) {
            nptnl[e.dst] = nptnl[src] + e.cost;
            last[e.dst] = &e;
          }
        }
      }
    } else {
      // O((V + E)logV)
      struct node_t {
        size_t id;
        cost_t dist;
        node_t(size_t id, cost_t dist) : id(id), dist(dist) {}
        bool operator<(const node_t &rhs) const { return rhs.dist < dist; }
      };
      std::priority_queue<node_t> que;
      for (size_t src{}; src != size(); ++src) {
        if (supp[src] > static_cast<cap_t>(0)) {
          nptnl[src] = 0;
          for (edge_t &e : adjs[src]) {
            if (supp[e.dst] > static_cast<cap_t>(0)) continue;
            if (e.avbl() && nptnl[e.dst] > e.cost) {
              que.emplace(e.dst, (nptnl[e.dst] = e.cost) - ptnl[e.dst]);
              last[e.dst] = &e;
            }
          }
        }
      }
      while (!que.empty()) {
        auto [src, ndist] = que.top();
        que.pop();
        if (ndist + ptnl[src] != nptnl[src]) continue;
        for (edge_t &e : adjs[src]) {
          if (e.avbl() && nptnl[e.dst] > nptnl[src] + e.cost) {
            que.emplace(e.dst,
                        (nptnl[e.dst] = nptnl[src] + e.cost) - ptnl[e.dst]);
            last[e.dst] = &e;
          }
        }
      }
    }
    ptnl.swap(nptnl);
  }

 public:
  using base::size;

  min_cost_flow(size_t n = 0)
      : base::flow_base(n), min_cost(0), total_cost(0), supp(n), ptnl(n) {}

  min_cost_flow(const min_cost_flow &other) : base::flow_base(other) {
    copy_member(other);
  }

  min_cost_flow &operator=(const min_cost_flow &other) {
    base::operator=(other);
    copy_member(other);
    return *this;
  }

  edge_t *add_edge(size_t src, size_t dst, const cost_t &cost);

  edge_t *add_edge(size_t src, size_t dst, const cap_t &cap,
                   const cost_t &cost) override {
    assert(src != dst);
    if (cost < static_cast<cost_t>(0)) {
      supp[src] -= cap;
      supp[dst] += cap;
      min_cost += cap * cost;
      total_cost -= cap * cost;
      return base::add_edge(dst, src, cap, -cost);
    }
    total_cost += cap * cost;
    return base::add_edge(src, dst, cap, cost);
  }

  edge_t *add_edge(size_t src, size_t dst, const cap_t &lower,
                   const cap_t &upper, const cost_t &cost) {
    assert(!(upper < lower));
    supp[src] -= lower;
    supp[dst] += lower;
    min_cost += lower * cost;
    return add_edge(src, dst, upper - lower, cost);
  }

  const cap_t &supply(size_t node, const cap_t &vol = 0) {
    assert(node < size());
    return supp[node] += vol;
  }

  const cap_t &demand(size_t node, const cap_t &vol) {
    return supply(node, -vol);
  }

  bool flow() {
    for (bool aug = true; aug;) {
      aug = false;
      std::vector<edge_t *> last(size());
      Dijkstra(last);
      std::vector<bool> shut(size());
      for (size_t dst{}; dst != size(); ++dst) {
        if (supp[dst] < static_cast<cap_t>(0) and last[dst]) {
          cap_t resid{-supp[dst]};
          size_t src{dst}, block{nil};
          while (last[src] && !shut[src]) {
            if (!(resid < last[src]->cap)) resid = last[block = src]->cap;
            src = last[src]->src;
          }
          if (shut[src])
            block = src;
          else {
            if (!(resid < supp[src])) {
              resid = supp[src];
              block = src;
            }
            for (edge_t *e{last[dst]}; e; e = last[e->src]) {
              e->cap -= resid;
              e->rev->cap += resid;
            }
            supp[src] -= resid;
            supp[dst] += resid;
            min_cost += ptnl[dst] * resid;
            aug = true;
          }
          if (~block) {
            for (size_t node{dst};; node = last[node]->src) {
              shut[node] = true;
              if (node == block) break;
            }
          }
        }
      }
    }
    return std::none_of(begin(supp), end(supp),
                        [](const cap_t &s) { return s < 0 || 0 < s; });
  }

  cost_t optimal() {
    assert(flow());
    return min_cost;
  }
};  // class min_cost_flow
#line 22 "other/h.cpp"

namespace workspace {
void main() {
  // start here!
  const int inf = 1e9;
  int n, m, x;
  cin >> n >> m >> x;

  min_cost_flow<i64, i64> base(n * 3);
  // make
  {
    for (int i = 0; i < n; i++) {
      int a, b, p;
      cin >> a >> b >> p;
      base.add_edge(3 * i + 1, 3 * i, inf, p);
      base.add_edge(3 * i, 3 * i + 1, inf, -1);
      base.add_edge(3 * i + 1, 3 * i + 2, inf, 0);
      if (i) base.add_edge(3 * (i - 1), 3 * i, inf, 0);
      base.supply(3 * i, -a);
      base.supply(3 * i + 1, a - b);
      base.supply(3 * i + 2, b);
    }
  }
  for (auto j = 0; j < m; ++j) {
    int u, v, f;
    cin >> u >> v >> f;
    --u, --v;
    if (f > 0) {
      base.add_edge(3 * v, 3 * u + 2, inf, 1);
    } else {
      base.add_edge(3 * u + 2, 3 * v, inf, 0);
    }
  }

  auto ok = [&](int t) -> bool {
    auto mcf = base;
    for (int i = 0; i < n; i++) {
      mcf.add_edge(3 * i + 2, 0, inf, t);
    }
    if (mcf.flow()) {
      auto opt = mcf.optimal();
      return opt >= x;
    }
    return false;
  };

  auto ans = binary_search(x + 100 * n + 1, -1, ok);
  if (ans > x + 100 * n)
    cout << "-1\n";
  else
    cout << ans << eol;
}
}
accuracy: 0.4222222222222222
time_ms: 40
memory_kb: 3676
final_rank: 17

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

using Int = long long;
const char newl = '\n';

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
template<typename T> void drop(const T &x){cout<<x<<endl;exit(0);}
template<typename T=int>
vector<T> read(size_t n){
  vector<T> ts(n);
  for(size_t i=0;i<n;i++) cin>>ts[i];
  return ts;
}


// O(m^2 \log n \log U)
// U: maximum capacity
enum Objective{
  MINIMIZE = +1,
  MAXIMIZE = -1,
};
template<typename Flow, typename Cost,
         Objective objective = Objective::MINIMIZE>
struct MinCostFlow{
  template<typename T> inline void chmin(T &x,T y){x=min(x,y);}

  struct Edge{
    int src,dst;
    Flow flow,cap;
    Cost cost;
    int rev;
    Edge(int src,int dst,Flow cap,Cost cost,int rev):
      src(src),dst(dst),flow(0),cap(cap),cost(cost),rev(rev){}
    Flow residual_cap()const{return cap-flow;}
  };

  struct EdgePtr{
    int v,e;
    EdgePtr(int v,int e):v(v),e(e){}
  };

  int n;
  vector<vector<Edge>> G;
  vector<Flow> b;
  vector<Cost> p;

  MinCostFlow(int n):n(n),G(n),b(n,0){}

  EdgePtr add_edge(int src,int dst,Flow lower,Flow upper,Cost cost){
    int e=G[src].size();
    int r=(src==dst?e+1:G[dst].size());
    assert(lower<=upper);
    G[src].emplace_back(src,dst,+upper,+cost*objective,r);
    G[dst].emplace_back(dst,src,-lower,-cost*objective,e);
    return EdgePtr(src,e);
  }

  const Edge &get_edge(EdgePtr ep)const{return G[ep.v][ep.e];}

  void push(Edge &e,Flow amount){
    e.flow+=amount;
    G[e.dst][e.rev].flow-=amount;
  }

  void add_supply(int v,Flow amount){b[v]+=amount;}
  void add_demand(int v,Flow amount){b[v]-=amount;}

  Cost residual_cost(const Edge &e){
    return e.cost+p[e.src]-p[e.dst];
  }

  vector<int> excess_vs,deficit_vs;
  void saturate_negative(const Flow delta){
    for(auto &es:G){
      for(auto &e:es){
        Flow cap=e.residual_cap();
        cap-=cap%delta;
        if(cap<0 or residual_cost(e)<0){
          push(e,cap);
          b[e.src]-=cap;
          b[e.dst]+=cap;
        }
      }
    }

    excess_vs.clear();
    deficit_vs.clear();
    for(int v=0;v<n;v++){
      if(b[v]>0) excess_vs.emplace_back(v);
      if(b[v]<0) deficit_vs.emplace_back(v);
    }
  }

  const Cost unreachable = std::numeric_limits<Cost>::max();
  Cost farthest;
  vector<Cost> dist;
  vector<Edge*> parent;

  struct P{
    Cost first;
    int second;
    P(Cost first,int second):first(first),second(second){}
    bool operator<(const P o)const{return first>o.first;}
  };

  priority_queue<P> pq;

  template<typename Predicate>
  void eliminate(vector<int> &vs,Predicate predicate){
    vs.erase(remove_if(begin(vs),end(vs),predicate),end(vs));
  }

  bool dual(const Flow delta){
    eliminate(excess_vs, [&](int v){return b[v]<+delta;});
    eliminate(deficit_vs,[&](int v){return b[v]>-delta;});

    dist.assign(n,unreachable);
    for(int v:excess_vs) pq.emplace(dist[v]=0,v);

    parent.assign(n,nullptr);
    auto emplace=[&](Edge& e){
      if(e.residual_cap()<delta) return;
      Cost nxt=dist[e.src]+residual_cost(e);
      if(nxt>=dist[e.dst]) return;
      pq.emplace(dist[e.dst]=nxt,e.dst);
      parent[e.dst]=&e;
    };

    farthest=0;
    int deficit_count=0;
    while(!pq.empty()){
      Cost d=pq.top().first;
      int v=pq.top().second;
      pq.pop();
      if(dist[v]<d) continue;
      farthest=d;

      if(b[v]<=-delta) deficit_count++;
      if(deficit_count>=(int)deficit_vs.size()) break;

      for(auto &e:G[v]) emplace(e);
    }
    pq=decltype(pq)();

    for(int v=0;v<n;v++)
      p[v]+=min(dist[v],farthest);

    return deficit_count>0;
  }

  void primal(const Flow delta){
    for(int t:deficit_vs){
      if(dist[t]>farthest) continue;
      Flow f=-b[t];
      int v;
      for(v=t;parent[v];v=parent[v]->src)
        chmin(f,parent[v]->residual_cap());
      chmin(f,b[v]);

      f-=f%delta;
      if(f<=0) continue;

      for(v=t;parent[v];){
        auto &e=*parent[v];
        push(e,f);
        int u=parent[v]->src;
        if(e.residual_cap()<=0) parent[v]=nullptr;
        v=u;
      }
      b[t]+=f;
      b[v]-=f;
    }
  }

  template<Flow SCALING_FACTOR=2>
  bool build(){
    p.resize(n);
    Flow max_flow=1;
    for(auto t:b) max_flow=max({max_flow,t,-t});
    for(auto &es:G)
      for(auto &e:es)
        max_flow=max({max_flow,e.residual_cap(),-e.residual_cap()});

    Flow delta=1;
    while(delta<max_flow) delta*=SCALING_FACTOR;
    for(;delta;delta/=SCALING_FACTOR){
      saturate_negative(delta);
      while(dual(delta)) primal(delta);
    }

    return excess_vs.empty() and deficit_vs.empty();
  }

  template<typename T=Cost>
  T get_cost(){
    T res=0;
    for(auto &es:G)
      for(auto &e:es)
        res+=T(e.flow)*T(e.cost)/T(objective);
    return res/T(2);
  }
  template<typename T=Cost> T get_gain(){return get_cost();}

  vector<Cost> get_potential(){
    fill(p.begin(),p.end(),0);
    for(int i=0;i<n;i++)
      for(auto &es:G)
        for(auto &e:es)
          if(e.residual_cap()>0)
            chmin(p[e.dst],p[e.src]+e.cost);
    return p;
  }
};

template<typename Flow, typename Cost>
using MaxGainFlow = MinCostFlow<Flow, Cost, Objective::MAXIMIZE>;


template<typename TV, const int N> void read_tuple_impl(TV&) {}
template<typename TV, const int N, typename Head, typename... Tail>
void read_tuple_impl(TV& ts) {
  get<N>(ts).emplace_back(*(istream_iterator<Head>(cin)));
  read_tuple_impl<TV, N+1, Tail...>(ts);
}
template<typename... Ts> decltype(auto) read_tuple(size_t n) {
  tuple<vector<Ts>...> ts;
  for(size_t i=0;i<n;i++) read_tuple_impl<decltype(ts), 0, Ts...>(ts);
  return ts;
}

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  using ll = long long;

  int n,m,need;
  cin>>n>>m>>need;
  auto [xs,ys,qs]=read_tuple<int, int, int>(n);
  auto [us,vs,fs]=read_tuple<int, int, int>(m);

  for(int i=0;i<m;i++) us[i]--,vs[i]--;

  auto st=[&](int i){return 0+i;};
  auto en=[&](int i){return n+i;};
  auto check=[&](ll T)->__int128_t{
    int Z=n+n;
    MinCostFlow<ll, ll> G(n+n+1);

    const ll INF = 1LL<<50;
    for(int i=0;i<n;i++){
      G.add_edge(st(i),Z,0,INF,0);
      G.add_edge(en(i),st(i),0,INF,-1);
      G.add_edge(Z,en(i),0,INF,T);
    }

    for(int i=0;i<m;i++){
      if(fs[i]==+1)
        G.add_edge(en(us[i]),st(vs[i]),0,INF,-1);
      if(fs[i]==-1)
        G.add_edge(st(vs[i]),en(us[i]),0,INF,0);
    }

    for(int i=0;i+1<n;i++)
      G.add_edge(st(i+1),st(i),0,INF,0);

    for(int i=0;i<n;i++){
      G.add_edge(st(i),en(i),0,xs[i]-ys[i],qs[i]);
      if(xs[i]>=0)
        G.add_edge(en(i),st(i),xs[i],INF,0);
      else
        G.add_edge(st(i),en(i),0,abs(xs[i]),0);
    }
    if(!G.build()) return -1;
    return G.get_cost<__int128_t>();
  };

  ll L=0,R=1e12;
  // check(L) < need
  // check(R) >= need
  if(check(R)<need) drop(-1);
  while(L+1<R){
    ll M=(L+R)>>1;
    if(check(M)>=need) R=M;
    else L=M;
  }
  cout<<R<<newl;
  return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 3592
final_rank: 5

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

using Int = long long;
const char newl = '\n';

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
template<typename T> void drop(const T &x){cout<<x<<endl;exit(0);}
template<typename T=int>
vector<T> read(size_t n){
  vector<T> ts(n);
  for(size_t i=0;i<n;i++) cin>>ts[i];
  return ts;
}


// O(m^2 \log n \log U)
// U: maximum capacity
enum Objective{
  MINIMIZE = +1,
  MAXIMIZE = -1,
};
template<typename Flow, typename Cost,
         Objective objective = Objective::MINIMIZE>
struct MinCostFlow{
  template<typename T> inline void chmin(T &x,T y){x=min(x,y);}

  struct Edge{
    int src,dst;
    Flow flow,cap;
    Cost cost;
    int rev;
    Edge(int src,int dst,Flow cap,Cost cost,int rev):
      src(src),dst(dst),flow(0),cap(cap),cost(cost),rev(rev){}
    Flow residual_cap()const{return cap-flow;}
  };

  struct EdgePtr{
    int v,e;
    EdgePtr(int v,int e):v(v),e(e){}
  };

  int n;
  vector<vector<Edge>> G;
  vector<Flow> b;
  vector<Cost> p;

  MinCostFlow(int n):n(n),G(n),b(n,0){}

  EdgePtr add_edge(int src,int dst,Flow lower,Flow upper,Cost cost){
    int e=G[src].size();
    int r=(src==dst?e+1:G[dst].size());
    assert(lower<=upper);
    G[src].emplace_back(src,dst,+upper,+cost*objective,r);
    G[dst].emplace_back(dst,src,-lower,-cost*objective,e);
    return EdgePtr(src,e);
  }

  const Edge &get_edge(EdgePtr ep)const{return G[ep.v][ep.e];}

  void push(Edge &e,Flow amount){
    e.flow+=amount;
    G[e.dst][e.rev].flow-=amount;
  }

  void add_supply(int v,Flow amount){b[v]+=amount;}
  void add_demand(int v,Flow amount){b[v]-=amount;}

  Cost residual_cost(const Edge &e){
    return e.cost+p[e.src]-p[e.dst];
  }

  vector<int> excess_vs,deficit_vs;
  void saturate_negative(const Flow delta){
    for(auto &es:G){
      for(auto &e:es){
        Flow cap=e.residual_cap();
        cap-=cap%delta;
        if(cap<0 or residual_cost(e)<0){
          push(e,cap);
          b[e.src]-=cap;
          b[e.dst]+=cap;
        }
      }
    }

    excess_vs.clear();
    deficit_vs.clear();
    for(int v=0;v<n;v++){
      if(b[v]>0) excess_vs.emplace_back(v);
      if(b[v]<0) deficit_vs.emplace_back(v);
    }
  }

  const Cost unreachable = std::numeric_limits<Cost>::max();
  Cost farthest;
  vector<Cost> dist;
  vector<Edge*> parent;

  struct P{
    Cost first;
    int second;
    P(Cost first,int second):first(first),second(second){}
    bool operator<(const P o)const{return first>o.first;}
  };

  priority_queue<P> pq;

  template<typename Predicate>
  void eliminate(vector<int> &vs,Predicate predicate){
    vs.erase(remove_if(begin(vs),end(vs),predicate),end(vs));
  }

  bool dual(const Flow delta){
    eliminate(excess_vs, [&](int v){return b[v]<+delta;});
    eliminate(deficit_vs,[&](int v){return b[v]>-delta;});

    dist.assign(n,unreachable);
    for(int v:excess_vs) pq.emplace(dist[v]=0,v);

    parent.assign(n,nullptr);
    auto emplace=[&](Edge& e){
      if(e.residual_cap()<delta) return;
      Cost nxt=dist[e.src]+residual_cost(e);
      if(nxt>=dist[e.dst]) return;
      pq.emplace(dist[e.dst]=nxt,e.dst);
      parent[e.dst]=&e;
    };

    farthest=0;
    int deficit_count=0;
    while(!pq.empty()){
      Cost d=pq.top().first;
      int v=pq.top().second;
      pq.pop();
      if(dist[v]<d) continue;
      farthest=d;

      if(b[v]<=-delta) deficit_count++;
      if(deficit_count>=(int)deficit_vs.size()) break;

      for(auto &e:G[v]) emplace(e);
    }
    pq=decltype(pq)();

    for(int v=0;v<n;v++)
      p[v]+=min(dist[v],farthest);

    return deficit_count>0;
  }

  void primal(const Flow delta){
    for(int t:deficit_vs){
      if(dist[t]>farthest) continue;
      Flow f=-b[t];
      int v;
      for(v=t;parent[v];v=parent[v]->src)
        chmin(f,parent[v]->residual_cap());
      chmin(f,b[v]);

      f-=f%delta;
      if(f<=0) continue;

      for(v=t;parent[v];){
        auto &e=*parent[v];
        push(e,f);
        int u=parent[v]->src;
        if(e.residual_cap()<=0) parent[v]=nullptr;
        v=u;
      }
      b[t]+=f;
      b[v]-=f;
    }
  }

  template<Flow SCALING_FACTOR=2>
  bool build(){
    p.resize(n);
    Flow max_flow=1;
    for(auto t:b) max_flow=max({max_flow,t,-t});
    for(auto &es:G)
      for(auto &e:es)
        max_flow=max({max_flow,e.residual_cap(),-e.residual_cap()});

    Flow delta=1;
    while(delta<max_flow) delta*=SCALING_FACTOR;
    for(;delta;delta/=SCALING_FACTOR){
      saturate_negative(delta);
      while(dual(delta)) primal(delta);
    }

    return excess_vs.empty() and deficit_vs.empty();
  }

  template<typename T=Cost>
  T get_cost(){
    T res=0;
    for(auto &es:G)
      for(auto &e:es)
        res+=T(e.flow)*T(e.cost)/T(objective);
    return res/T(2);
  }
  template<typename T=Cost> T get_gain(){return get_cost();}

  vector<Cost> get_potential(){
    fill(p.begin(),p.end(),0);
    for(int i=0;i<n;i++)
      for(auto &es:G)
        for(auto &e:es)
          if(e.residual_cap()>0)
            chmin(p[e.dst],p[e.src]+e.cost);
    return p;
  }
};

template<typename Flow, typename Cost>
using MaxGainFlow = MinCostFlow<Flow, Cost, Objective::MAXIMIZE>;


template<typename TV, const int N> void read_tuple_impl(TV&) {}
template<typename TV, const int N, typename Head, typename... Tail>
void read_tuple_impl(TV& ts) {
  get<N>(ts).emplace_back(*(istream_iterator<Head>(cin)));
  read_tuple_impl<TV, N+1, Tail...>(ts);
}
template<typename... Ts> decltype(auto) read_tuple(size_t n) {
  tuple<vector<Ts>...> ts;
  for(size_t i=0;i<n;i++) read_tuple_impl<decltype(ts), 0, Ts...>(ts);
  return ts;
}

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  using ll = long long;

  int n,m,need;
  cin>>n>>m>>need;
  auto [xs,ys,qs]=read_tuple<int, int, int>(n);
  auto [us,vs,fs]=read_tuple<int, int, int>(m);

  for(int i=0;i<m;i++) us[i]--,vs[i]--;

  auto st=[&](int i){return 0+i;};
  auto en=[&](int i){return n+i;};
  auto check=[&](ll T)->__int128_t{
    int Z=n+n;
    MinCostFlow<ll, ll> G(n+n+1);

    const ll INF = 1LL<<40;
    for(int i=0;i<n;i++){
      G.add_edge(st(i),Z,0,INF,0);
      G.add_edge(en(i),st(i),0,INF,-1);
      G.add_edge(Z,en(i),0,INF,T);
    }

    for(int i=0;i<m;i++){
      if(fs[i]==+1)
        G.add_edge(en(us[i]),st(vs[i]),0,INF,-1);
      if(fs[i]==-1)
        G.add_edge(st(vs[i]),en(us[i]),0,INF,0);
    }

    for(int i=0;i+1<n;i++)
      G.add_edge(st(i+1),st(i),0,INF,0);

    for(int i=0;i<n;i++){
      G.add_edge(st(i),en(i),0,xs[i]-ys[i],qs[i]);
      if(xs[i]>=0)
        G.add_edge(en(i),st(i),xs[i],INF,0);
      else
        G.add_edge(st(i),en(i),0,abs(xs[i]),0);
    }
    if(!G.build()) return -1;
    return G.get_cost<__int128_t>();
  };

  ll L=0,R=1e9;
  // check(L) < need
  // check(R) >= need
  if(check(R)<need) drop(-1);
  while(L+1<R){
    ll M=(L+R)>>1;
    if(check(M)>=need) R=M;
    else L=M;
  }
  cout<<R<<newl;
  return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3592
final_rank: 2

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

using Int = long long;
const char newl = '\n';

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
template<typename T> void drop(const T &x){cout<<x<<endl;exit(0);}
template<typename T=int>
vector<T> read(size_t n){
  vector<T> ts(n);
  for(size_t i=0;i<n;i++) cin>>ts[i];
  return ts;
}


// O(m^2 \log n \log U)
// U: maximum capacity
enum Objective{
  MINIMIZE = +1,
  MAXIMIZE = -1,
};
template<typename Flow, typename Cost,
         Objective objective = Objective::MINIMIZE>
struct MinCostFlow{
  template<typename T> inline void chmin(T &x,T y){x=min(x,y);}

  struct Edge{
    int src,dst;
    Flow flow,cap;
    Cost cost;
    int rev;
    Edge(int src,int dst,Flow cap,Cost cost,int rev):
      src(src),dst(dst),flow(0),cap(cap),cost(cost),rev(rev){}
    Flow residual_cap()const{return cap-flow;}
  };

  struct EdgePtr{
    int v,e;
    EdgePtr(int v,int e):v(v),e(e){}
  };

  int n;
  vector<vector<Edge>> G;
  vector<Flow> b;
  vector<Cost> p;

  MinCostFlow(int n):n(n),G(n),b(n,0){}

  EdgePtr add_edge(int src,int dst,Flow lower,Flow upper,Cost cost){
    int e=G[src].size();
    int r=(src==dst?e+1:G[dst].size());
    assert(lower<=upper);
    G[src].emplace_back(src,dst,+upper,+cost*objective,r);
    G[dst].emplace_back(dst,src,-lower,-cost*objective,e);
    return EdgePtr(src,e);
  }

  const Edge &get_edge(EdgePtr ep)const{return G[ep.v][ep.e];}

  void push(Edge &e,Flow amount){
    e.flow+=amount;
    G[e.dst][e.rev].flow-=amount;
  }

  void add_supply(int v,Flow amount){b[v]+=amount;}
  void add_demand(int v,Flow amount){b[v]-=amount;}

  Cost residual_cost(const Edge &e){
    return e.cost+p[e.src]-p[e.dst];
  }

  vector<int> excess_vs,deficit_vs;
  void saturate_negative(const Flow delta){
    for(auto &es:G){
      for(auto &e:es){
        Flow cap=e.residual_cap();
        cap-=cap%delta;
        if(cap<0 or residual_cost(e)<0){
          push(e,cap);
          b[e.src]-=cap;
          b[e.dst]+=cap;
        }
      }
    }

    excess_vs.clear();
    deficit_vs.clear();
    for(int v=0;v<n;v++){
      if(b[v]>0) excess_vs.emplace_back(v);
      if(b[v]<0) deficit_vs.emplace_back(v);
    }
  }

  const Cost unreachable = std::numeric_limits<Cost>::max();
  Cost farthest;
  vector<Cost> dist;
  vector<Edge*> parent;

  struct P{
    Cost first;
    int second;
    P(Cost first,int second):first(first),second(second){}
    bool operator<(const P o)const{return first>o.first;}
  };

  priority_queue<P> pq;

  template<typename Predicate>
  void eliminate(vector<int> &vs,Predicate predicate){
    vs.erase(remove_if(begin(vs),end(vs),predicate),end(vs));
  }

  bool dual(const Flow delta){
    eliminate(excess_vs, [&](int v){return b[v]<+delta;});
    eliminate(deficit_vs,[&](int v){return b[v]>-delta;});

    dist.assign(n,unreachable);
    for(int v:excess_vs) pq.emplace(dist[v]=0,v);

    parent.assign(n,nullptr);
    auto emplace=[&](Edge& e){
      if(e.residual_cap()<delta) return;
      Cost nxt=dist[e.src]+residual_cost(e);
      if(nxt>=dist[e.dst]) return;
      pq.emplace(dist[e.dst]=nxt,e.dst);
      parent[e.dst]=&e;
    };

    farthest=0;
    int deficit_count=0;
    while(!pq.empty()){
      Cost d=pq.top().first;
      int v=pq.top().second;
      pq.pop();
      if(dist[v]<d) continue;
      farthest=d;

      if(b[v]<=-delta) deficit_count++;
      if(deficit_count>=(int)deficit_vs.size()) break;

      for(auto &e:G[v]) emplace(e);
    }
    pq=decltype(pq)();

    for(int v=0;v<n;v++)
      p[v]+=min(dist[v],farthest);

    return deficit_count>0;
  }

  void primal(const Flow delta){
    for(int t:deficit_vs){
      if(dist[t]>farthest) continue;
      Flow f=-b[t];
      int v;
      for(v=t;parent[v];v=parent[v]->src)
        chmin(f,parent[v]->residual_cap());
      chmin(f,b[v]);

      f-=f%delta;
      if(f<=0) continue;

      for(v=t;parent[v];){
        auto &e=*parent[v];
        push(e,f);
        int u=parent[v]->src;
        if(e.residual_cap()<=0) parent[v]=nullptr;
        v=u;
      }
      b[t]+=f;
      b[v]-=f;
    }
  }

  template<Flow SCALING_FACTOR=2>
  bool build(){
    p.resize(n);
    Flow max_flow=1;
    for(auto t:b) max_flow=max({max_flow,t,-t});
    for(auto &es:G)
      for(auto &e:es)
        max_flow=max({max_flow,e.residual_cap(),-e.residual_cap()});

    Flow delta=1;
    while(delta<max_flow) delta*=SCALING_FACTOR;
    for(;delta;delta/=SCALING_FACTOR){
      saturate_negative(delta);
      while(dual(delta)) primal(delta);
    }

    return excess_vs.empty() and deficit_vs.empty();
  }

  template<typename T=Cost>
  T get_cost(){
    T res=0;
    for(auto &es:G)
      for(auto &e:es)
        res+=T(e.flow)*T(e.cost)/T(objective);
    return res/T(2);
  }
  template<typename T=Cost> T get_gain(){return get_cost();}

  vector<Cost> get_potential(){
    fill(p.begin(),p.end(),0);
    for(int i=0;i<n;i++)
      for(auto &es:G)
        for(auto &e:es)
          if(e.residual_cap()>0)
            chmin(p[e.dst],p[e.src]+e.cost);
    return p;
  }
};

template<typename Flow, typename Cost>
using MaxGainFlow = MinCostFlow<Flow, Cost, Objective::MAXIMIZE>;


template<typename TV, const int N> void read_tuple_impl(TV&) {}
template<typename TV, const int N, typename Head, typename... Tail>
void read_tuple_impl(TV& ts) {
  get<N>(ts).emplace_back(*(istream_iterator<Head>(cin)));
  read_tuple_impl<TV, N+1, Tail...>(ts);
}
template<typename... Ts> decltype(auto) read_tuple(size_t n) {
  tuple<vector<Ts>...> ts;
  for(size_t i=0;i<n;i++) read_tuple_impl<decltype(ts), 0, Ts...>(ts);
  return ts;
}

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  using ll = long long;

  int n,m,need;
  cin>>n>>m>>need;
  auto [xs,ys,qs]=read_tuple<int, int, int>(n);
  auto [us,vs,fs]=read_tuple<int, int, int>(m);

  for(int i=0;i<m;i++) us[i]--,vs[i]--;

  auto st=[&](int i){return 0+i;};
  auto en=[&](int i){return n+i;};
  auto check=[&](ll T)->ll{
    int Z=n+n;
    MinCostFlow<ll, ll> G(n+n+1);

    const ll INF = 1LL<<60;
    for(int i=0;i<n;i++){
      G.add_edge(st(i),Z,0,INF,0);
      G.add_edge(en(i),st(i),0,INF,-1);
      G.add_edge(Z,en(i),0,INF,T);
    }

    for(int i=0;i<m;i++){
      if(fs[i]==+1)
        G.add_edge(en(us[i]),st(vs[i]),0,INF,-1);
      if(fs[i]==-1)
        G.add_edge(st(vs[i]),en(us[i]),0,INF,0);
    }

    for(int i=0;i+1<n;i++)
      G.add_edge(st(i+1),st(i),0,INF,0);

    for(int i=0;i<n;i++){
      G.add_edge(st(i),en(i),0,xs[i]-ys[i],qs[i]);
      if(xs[i]>=0)
        G.add_edge(en(i),st(i),xs[i],INF,0);
      else
        G.add_edge(st(i),en(i),0,abs(xs[i]),0);
    }
    if(!G.build()) return -1;
    return G.get_cost();
  };

  ll L=0,R=1e9;
  // check(L) < need
  // check(R) >= need
  if(check(R)<need) drop(-1);
  while(L+1<R){
    int M=(L+R)>>1;
    if(check(M)>=need) R=M;
    else L=M;
  }
  cout<<R<<newl;
  return 0;
}
accuracy: 0.13333333333333333
time_ms: 10
memory_kb: 3468
final_rank: 20

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

using Int = long long;
const char newl = '\n';

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
template<typename T> void drop(const T &x){cout<<x<<endl;exit(0);}
template<typename T=int>
vector<T> read(size_t n){
  vector<T> ts(n);
  for(size_t i=0;i<n;i++) cin>>ts[i];
  return ts;
}


// O(m^2 \log n \log U)
// U: maximum capacity
enum Objective{
  MINIMIZE = +1,
  MAXIMIZE = -1,
};
template<typename Flow, typename Cost,
         Objective objective = Objective::MINIMIZE>
struct MinCostFlow{
  template<typename T> inline void chmin(T &x,T y){x=min(x,y);}

  struct Edge{
    int src,dst;
    Flow flow,cap;
    Cost cost;
    int rev;
    Edge(int src,int dst,Flow cap,Cost cost,int rev):
      src(src),dst(dst),flow(0),cap(cap),cost(cost),rev(rev){}
    Flow residual_cap()const{return cap-flow;}
  };

  struct EdgePtr{
    int v,e;
    EdgePtr(int v,int e):v(v),e(e){}
  };

  int n;
  vector<vector<Edge>> G;
  vector<Flow> b;
  vector<Cost> p;

  MinCostFlow(int n):n(n),G(n),b(n,0){}

  EdgePtr add_edge(int src,int dst,Flow lower,Flow upper,Cost cost){
    int e=G[src].size();
    int r=(src==dst?e+1:G[dst].size());
    assert(lower<=upper);
    G[src].emplace_back(src,dst,+upper,+cost*objective,r);
    G[dst].emplace_back(dst,src,-lower,-cost*objective,e);
    return EdgePtr(src,e);
  }

  const Edge &get_edge(EdgePtr ep)const{return G[ep.v][ep.e];}

  void push(Edge &e,Flow amount){
    e.flow+=amount;
    G[e.dst][e.rev].flow-=amount;
  }

  void add_supply(int v,Flow amount){b[v]+=amount;}
  void add_demand(int v,Flow amount){b[v]-=amount;}

  Cost residual_cost(const Edge &e){
    return e.cost+p[e.src]-p[e.dst];
  }

  vector<int> excess_vs,deficit_vs;
  void saturate_negative(const Flow delta){
    for(auto &es:G){
      for(auto &e:es){
        Flow cap=e.residual_cap();
        cap-=cap%delta;
        if(cap<0 or residual_cost(e)<0){
          push(e,cap);
          b[e.src]-=cap;
          b[e.dst]+=cap;
        }
      }
    }

    excess_vs.clear();
    deficit_vs.clear();
    for(int v=0;v<n;v++){
      if(b[v]>0) excess_vs.emplace_back(v);
      if(b[v]<0) deficit_vs.emplace_back(v);
    }
  }

  const Cost unreachable = std::numeric_limits<Cost>::max();
  Cost farthest;
  vector<Cost> dist;
  vector<Edge*> parent;

  struct P{
    Cost first;
    int second;
    P(Cost first,int second):first(first),second(second){}
    bool operator<(const P o)const{return first>o.first;}
  };

  priority_queue<P> pq;

  template<typename Predicate>
  void eliminate(vector<int> &vs,Predicate predicate){
    vs.erase(remove_if(begin(vs),end(vs),predicate),end(vs));
  }

  bool dual(const Flow delta){
    eliminate(excess_vs, [&](int v){return b[v]<+delta;});
    eliminate(deficit_vs,[&](int v){return b[v]>-delta;});

    dist.assign(n,unreachable);
    for(int v:excess_vs) pq.emplace(dist[v]=0,v);

    parent.assign(n,nullptr);
    auto emplace=[&](Edge& e){
      if(e.residual_cap()<delta) return;
      Cost nxt=dist[e.src]+residual_cost(e);
      if(nxt>=dist[e.dst]) return;
      pq.emplace(dist[e.dst]=nxt,e.dst);
      parent[e.dst]=&e;
    };

    farthest=0;
    int deficit_count=0;
    while(!pq.empty()){
      Cost d=pq.top().first;
      int v=pq.top().second;
      pq.pop();
      if(dist[v]<d) continue;
      farthest=d;

      if(b[v]<=-delta) deficit_count++;
      if(deficit_count>=(int)deficit_vs.size()) break;

      for(auto &e:G[v]) emplace(e);
    }
    pq=decltype(pq)();

    for(int v=0;v<n;v++)
      p[v]+=min(dist[v],farthest);

    return deficit_count>0;
  }

  void primal(const Flow delta){
    for(int t:deficit_vs){
      if(dist[t]>farthest) continue;
      Flow f=-b[t];
      int v;
      for(v=t;parent[v];v=parent[v]->src)
        chmin(f,parent[v]->residual_cap());
      chmin(f,b[v]);

      f-=f%delta;
      if(f<=0) continue;

      for(v=t;parent[v];){
        auto &e=*parent[v];
        push(e,f);
        int u=parent[v]->src;
        if(e.residual_cap()<=0) parent[v]=nullptr;
        v=u;
      }
      b[t]+=f;
      b[v]-=f;
    }
  }

  template<Flow SCALING_FACTOR=2>
  bool build(){
    p.resize(n);
    Flow max_flow=1;
    for(auto t:b) max_flow=max({max_flow,t,-t});
    for(auto &es:G)
      for(auto &e:es)
        max_flow=max({max_flow,e.residual_cap(),-e.residual_cap()});

    Flow delta=1;
    while(delta<max_flow) delta*=SCALING_FACTOR;
    for(;delta;delta/=SCALING_FACTOR){
      saturate_negative(delta);
      while(dual(delta)) primal(delta);
    }

    return excess_vs.empty() and deficit_vs.empty();
  }

  template<typename T=Cost>
  T get_cost(){
    T res=0;
    for(auto &es:G)
      for(auto &e:es)
        res+=T(e.flow)*T(e.cost)/T(objective);
    return res/T(2);
  }
  template<typename T=Cost> T get_gain(){return get_cost();}

  vector<Cost> get_potential(){
    fill(p.begin(),p.end(),0);
    for(int i=0;i<n;i++)
      for(auto &es:G)
        for(auto &e:es)
          if(e.residual_cap()>0)
            chmin(p[e.dst],p[e.src]+e.cost);
    return p;
  }
};

template<typename Flow, typename Cost>
using MaxGainFlow = MinCostFlow<Flow, Cost, Objective::MAXIMIZE>;


template<typename TV, const int N> void read_tuple_impl(TV&) {}
template<typename TV, const int N, typename Head, typename... Tail>
void read_tuple_impl(TV& ts) {
  get<N>(ts).emplace_back(*(istream_iterator<Head>(cin)));
  read_tuple_impl<TV, N+1, Tail...>(ts);
}
template<typename... Ts> decltype(auto) read_tuple(size_t n) {
  tuple<vector<Ts>...> ts;
  for(size_t i=0;i<n;i++) read_tuple_impl<decltype(ts), 0, Ts...>(ts);
  return ts;
}

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);
  using ll = long long;

  int n,m,need;
  cin>>n>>m>>need;
  auto [xs,ys,qs]=read_tuple<int, int, int>(n);
  auto [us,vs,fs]=read_tuple<int, int, int>(m);

  for(int i=0;i<m;i++) us[i]--,vs[i]--;

  auto st=[&](int i){return 0+i;};
  auto en=[&](int i){return n+i;};
  auto check=[&](ll T)->ll{
    int Z=n+n;
    MinCostFlow<ll, ll> G(n+n+1);

    const ll INF = 1LL<<40;
    for(int i=0;i<n;i++){
      G.add_edge(st(i),Z,0,INF,0);
      G.add_edge(en(i),st(i),0,INF,-1);
      G.add_edge(Z,en(i),0,INF,T);
    }

    for(int i=0;i<m;i++){
      if(fs[i]==+1)
        G.add_edge(en(us[i]),st(vs[i]),0,INF,-1);
      if(fs[i]==-1)
        G.add_edge(st(vs[i]),en(us[i]),0,INF,0);
    }

    for(int i=0;i+1<n;i++)
      G.add_edge(st(i+1),st(i),0,INF,0);

    for(int i=0;i<n;i++){
      G.add_edge(st(i),en(i),0,xs[i]-ys[i],qs[i]);
      if(xs[i]>=0)
        G.add_edge(en(i),st(i),xs[i],INF,0);
      else
        G.add_edge(st(i),en(i),0,abs(xs[i]),0);
    }
    if(!G.build()) return -1;
    return G.get_cost();
  };

  ll L=0,R=1e9;
  // check(L) < need
  // check(R) >= need
  if(check(R)<need) drop(-1);
  while(L+1<R){
    int M=(L+R)>>1;
    if(check(M)>=need) R=M;
    else L=M;
  }
  cout<<R<<newl;
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3584
final_rank: 3

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

#define int long long

// Ford-Fulkerson 法による 最大流 O( F |E| )
// Bellman-Ford 法による 最小費用流 O( F |V| |E| )
// [条件に注意] Dijkstra 法による 最小費用流 O( F |E| log |V| )

template <typename CapTp=int, typename CostTp=int>
struct Edge {
    int to, rev;
    CapTp cap; CostTp cost;
    bool is_rev;
    Edge(int t, bool f, int r, CapTp ca, CostTp co=0)
        : to(t), rev(r), cap(ca), cost(co), is_rev(f) {}
};

template <typename CapTp=int, typename CostTp=int>
struct Flow {
    using Graph = vector< vector< Edge<CapTp, CostTp> > >;
    Graph G; const CapTp IA; const CostTp IO, NIL;
    vector< pair<int, int> > r_edges;
    vector<CostTp> dist, pot;
    vector<int> prevv, preve;

    Flow(int N_, CapTp IA_=1<<29, CostTp IO_=1<<29, CostTp NIL_=-1)
        : G(N_), IA(IA_), IO(IO_), NIL(NIL_), r_edges(),
          dist(N_), pot(N_), prevv(N_), preve(N_) {}
    // 辺を追加 (from -> to に流量 ca, コスト co)
    void add_edge(int from, int to, CapTp ca, CostTp co=0) {
        G[from].emplace_back(to, false, G[to].size(), ca, co);
        G[to].emplace_back(from, true, G[from].size() - 1, 0, -co);
        r_edges.emplace_back(to, G[to].size() - 1);
    }
    // k 番目の辺にいくつ流れたか
    CapTp get_flowed_cap(size_t k) {
        if(r_edges.size() <= k) return -1;
        int v, i; tie(v, i) = r_edges[k];
        return G[v][i].cap;
    }
    // s -> t 最大流
    CapTp max_flow(int s, int t) {
        vector<bool> used(G.size());
        auto dfs = [&](auto &&func, int v, int t, CapTp f) -> CapTp {
            if(v == t) return f;
            used[v] = true;
            for(auto &e : G[v]) {
                if(used[e.to] or e.cap == 0) continue;
                CapTp d = func(func, e.to, t, min(f, e.cap));
                if(d == 0) continue;
                e.cap -= d; G[e.to][e.rev].cap += d;
                return d;
            }
            return 0;
        };

        CapTp res(0);
        while(true) {
            fill(used.begin(), used.end(), false);
            CapTp delta = dfs(dfs, s, t, IA);
            if(delta == 0) return res;
            res += delta;
        }
    }
    // ベルマンフォードをつかって最小費用流
    CostTp mincost_flow(int s, int t, CapTp f) {
        CostTp res(0);
        while(f > 0) {
            fill(dist.begin(), dist.end(), IO);
            dist[s] = 0;
            while(1) {
                bool upd = false;
                for(int v=0; v<(int)G.size(); v++) {
                    if(dist[v] == IO) continue;
                    for(size_t i=0; i<G[v].size(); i++) {
                        auto &e = G[v][i];
                        if(e.cap == 0 or dist[e.to] <= dist[v] + e.cost) continue;
                        dist[e.to] = dist[v] + e.cost;
                        prevv[e.to] = v, preve[e.to] = i;
                        upd = true;
                    }
                }
                if(!upd) break;
            }

            if(dist[t] == IO) return NIL;
            CapTp d = f;
            for(int v=t; v!=s; v=prevv[v]) d = min(d, G[prevv[v]][preve[v]].cap);
            f -= d; res += d * dist[t];
            for(int v=t; v!=s; v=prevv[v]) {
                auto &e = G[prevv[v]][preve[v]];
                e.cap -= d, G[v][e.rev].cap += d;
            }
        }
        return res;
    }
    // ポテンシャルの導入により、ダイクストラ法で最小費用流を解く
    // [仮定している条件]
    //     1. グラフに負の閉路が存在しない (流量の 0 初期化のため)
    //        もし存在するならベルマンフォードで負の閉路を見つけ
    //        そこに流せるだけ流してスタート
    //     2. グラフに負の辺が存在しない (pot_0 の計算可能性)
    //        もし存在する場合は最初のみベルマンフォードを使う必要あり
    CostTp fast_mincost_flow(int s, int t, CapTp f) {
        CostTp res(0);
        fill(pot.begin(), pot.end(), CostTp(0));

        while(f > 0) {
            using PT = pair<CostTp, int>;
            priority_queue< PT, vector<PT>, greater<PT> > que;
            fill(dist.begin(), dist.end(), IO);

            dist[s] = 0;
            que.push(make_pair(0, s));
            while(!que.empty()) {
                PT cur = que.top(); que.pop();
                int v = cur.second;
                if(dist[v] < cur.first) continue;
                for(size_t i=0; i<G[v].size(); i++) {
                    auto& e = G[v][i];
                    if(e.cap > 0 and dist[e.to] > dist[v] + e.cost + pot[v] - pot[e.to]) {
                        dist[e.to] = dist[v] + e.cost + pot[v] - pot[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        que.push(make_pair(dist[e.to], e.to));
                    }
                }
            }
            if(dist[t] == IO) {
                return NIL;
            }
            for(int v=0; v<(int)G.size(); v++) pot[v] += dist[v];

            CapTp d = f;
            for(int v=t; v!=s; v=prevv[v]) {
                d = min(d, G[prevv[v]][preve[v]].cap);
            }
            f -= d;
            res += d * pot[t];
            for(int v=t; v!=s; v=prevv[v]) {
                auto& e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return res;
    }
};

template <typename cap_tp=int, typename cost_tp=int,
          template<typename, typename> class flow_fw=Flow>
struct GeneralizedMincostFlow {
private:
    flow_fw<cap_tp, cost_tp> fl;
    vector<cap_tp> D;
    int N, source, sink;
    cap_tp Z_cap;
    cost_tp Z_cost, ofs, ng;
    int edge_id;

public:
    GeneralizedMincostFlow(int N_,
                           cost_tp ng_=-1,
                           cap_tp IA=1<<29, cost_tp IO=1<<29,
                           cap_tp zero_cap=0, cost_tp zero_cost=0)
        : fl(N_+2, IA, IO, ng_), D(N_), N(N_), source(N_), sink(N_+1),
          Z_cap(zero_cap), Z_cost(zero_cost), ofs(zero_cost), ng(ng_),
          edge_id(0) {}

    int add_edge(int u, int v, cap_tp low, cap_tp high, cost_tp cost) {
        assert(low <= high);
        if(low < Z_cap) {
            add_edge(v, u, -low, -low, -cost);
            add_edge(u, v, 0, high - low, +cost);
            return -1; // TODO ?
        }
        int id = -1;

        // コストが負の場合
        if(cost < Z_cost) {
            // 流すだけ得なので high 流れたことにする
            ofs += high * cost;
            D[u] -= high; D[v] += high;
            // 目一杯流したのを high - low 分だけキャンセル可能
            if(high - low > Z_cap) {
                id = edge_id++;
                fl.add_edge(v, u, high - low, -cost);
            }
        }
        else {
            // v 側に low 流れたことにする
            ofs += low * cost;
            D[u] -= low; D[v] += low;
            // high - low 分の辺を張る
            if(high - low > Z_cap) {
                id = edge_id++;
                fl.add_edge(u, v, high - low, cost);
            }
        }
        return id;
    }
    int add_edge(int u, int v, cap_tp cap, cost_tp cost) {
        return add_edge(u, v, Z_cap, cap, cost);
    }
    void change_d(int u, cap_tp delta) {
        D[u] += delta;
    }

    cost_tp mincost_flow() {
        cap_tp sum_d = 0;
        for(int i=0; i<N; i++) {
            if(D[i] > 0) {
                fl.add_edge(source, i, D[i], 0);
                sum_d += D[i];
            }
            else {
                fl.add_edge(i, sink, -D[i], 0);
            }
        }

        cost_tp res = fl.fast_mincost_flow(source, sink, sum_d);
        if(res == fl.NIL) return ng;
        else return ofs + res;
    }

    cap_tp get_flowed_cap(size_t k) {
        return fl.get_flowed_cap(k);
    }

    cap_tp operator[](size_t k) {
        return fl.pot[k];
    }
};

const int INF=1e9;

signed main(){
  int n,m,x;cin>>n>>m>>x;
  vector<int> a(n),b(n),p(n),u(m),v(m),f(m);
  for(int i=0;i<n;i++){
    cin>>a[i]>>b[i]>>p[i];
    x-=a[i]*p[i];
  }
  for(int i=0;i<m;i++){
    cin>>u[i]>>v[i]>>f[i];
    u[i]--;v[i]--;
  }
  int ng=-1,ok=INF;//ok時間あれば仕事量xを達成できる
  while(ok-ng>1){
    int mid=(ok+ng)>>1;
    GeneralizedMincostFlow<> fl(n*2+1);//[0,n)がs[i]、[n,2n-1)がt[i]、2nがz
    int z=2*n;
    for(int i=0;i<n;i++){
      if(i)fl.add_edge(i,i-1,0,INF,0);
      fl.add_edge(i,z,0,INF,0);
      fl.add_edge(n+i,i,0,INF,-1);
      fl.add_edge(z,n+i,0,INF,mid);
      fl.add_edge(n+i,i,b[i],a[i],-p[i]);
    }
    for(int i=0;i<m;i++){
      if(~f[i])fl.add_edge(u[i]+n,v[i],0,INF,-1);
      else fl.add_edge(v[i],u[i]+n,0,INF,0);
    }
    if(x<=fl.mincost_flow())ok=mid;
    else ng=mid;
  }
  if(ng>1e7)cout<<-1<<endl;
  else cout<<ok<<endl;
}
accuracy: 1
time_ms: 350
memory_kb: 3276
final_rank: 1

code_snippet: #include <vector>
#include <utility>
#include <tuple>
#include <queue>
#include <algorithm>
#include <cassert>
#include <iostream>
using namespace std;
using ll = long long int;

// Ford-Fulkerson 法による 最大流 O( F |E| )
// Bellman-Ford 法による 最小費用流 O( F |V| |E| )
// [条件に注意] Dijkstra 法による 最小費用流 O( F |E| log |V| )

template <typename CapTp=int, typename CostTp=int>
struct Edge {
    int to, rev;
    CapTp cap; CostTp cost;
    bool is_rev;
    Edge(int t, bool f, int r, CapTp ca, CostTp co=0)
        : to(t), rev(r), cap(ca), cost(co), is_rev(f) {}
};

template <typename CapTp=int, typename CostTp=int>
struct Flow {
    using Graph = vector< vector< Edge<CapTp, CostTp> > >;
    Graph G; const CapTp IA; const CostTp IO, NIL;
    vector< pair<int, int> > r_edges;
    vector<CostTp> dist, pot;
    vector<int> prevv, preve;
    
    Flow(int N_, CapTp IA_=1<<29, CostTp IO_=1<<29, CostTp NIL_=-1)
        : G(N_), IA(IA_), IO(IO_), NIL(NIL_), r_edges(),
          dist(N_), pot(N_), prevv(N_), preve(N_) {}
    // 辺を追加 (from -> to に流量 ca, コスト co)
    void add_edge(int from, int to, CapTp ca, CostTp co=0) {
        G[from].emplace_back(to, false, G[to].size(), ca, co);
        G[to].emplace_back(from, true, G[from].size() - 1, 0, -co);
        r_edges.emplace_back(to, G[to].size() - 1);
    }
    // k 番目の辺にいくつ流れたか
    CapTp get_flowed_cap(size_t k) {
        if(r_edges.size() <= k) return -1;
        int v, i; tie(v, i) = r_edges[k];
        return G[v][i].cap;
    }
    // s -> t 最大流
    CapTp max_flow(int s, int t) {
        vector<bool> used(G.size());
        auto dfs = [&](auto &&func, int v, int t, CapTp f) -> CapTp {
            if(v == t) return f;
            used[v] = true;
            for(auto &e : G[v]) {
                if(used[e.to] or e.cap == 0) continue;
                CapTp d = func(func, e.to, t, min(f, e.cap));
                if(d == 0) continue;
                e.cap -= d; G[e.to][e.rev].cap += d;
                return d;
            }
            return 0;
        };

        CapTp res(0);
        while(true) {
            fill(used.begin(), used.end(), false);
            CapTp delta = dfs(dfs, s, t, IA);
            if(delta == 0) return res;
            res += delta;
        }
    }
    // ベルマンフォードをつかって最小費用流
    CostTp mincost_flow(int s, int t, CapTp f) {
        CostTp res(0);
        while(f > 0) {
            fill(dist.begin(), dist.end(), IO);
            dist[s] = 0;
            while(1) {
                bool upd = false;
                for(int v=0; v<(int)G.size(); v++) {
                    if(dist[v] == IO) continue;
                    for(size_t i=0; i<G[v].size(); i++) {
                        auto &e = G[v][i];
                        if(e.cap == 0 or dist[e.to] <= dist[v] + e.cost) continue;
                        dist[e.to] = dist[v] + e.cost;
                        prevv[e.to] = v, preve[e.to] = i;
                        upd = true;
                    }
                }
                if(!upd) break;
            }

            if(dist[t] == IO) return NIL;
            CapTp d = f;
            for(int v=t; v!=s; v=prevv[v]) d = min(d, G[prevv[v]][preve[v]].cap);
            f -= d; res += d * dist[t];
            for(int v=t; v!=s; v=prevv[v]) {
                auto &e = G[prevv[v]][preve[v]];
                e.cap -= d, G[v][e.rev].cap += d;
            }
        }
        return res;
    }
    // ポテンシャルの導入により、ダイクストラ法で最小費用流を解く
    // [仮定している条件]
    //     1. グラフに負の閉路が存在しない (流量の 0 初期化のため)
    //        もし存在するならベルマンフォードで負の閉路を見つけ
    //        そこに流せるだけ流してスタート
    //     2. グラフに負の辺が存在しない (pot_0 の計算可能性)
    //        もし存在する場合は最初のみベルマンフォードを使う必要あり
    CostTp fast_mincost_flow(int s, int t, CapTp f) {
        CostTp res(0);
        fill(pot.begin(), pot.end(), CostTp(0));

        while(f > 0) {
            using PT = pair<CostTp, int>;
            priority_queue< PT, vector<PT>, greater<PT> > que;
            fill(dist.begin(), dist.end(), IO);

            dist[s] = 0;
            que.push(make_pair(0, s));
            while(!que.empty()) {
                PT cur = que.top(); que.pop();
                int v = cur.second;
                if(dist[v] < cur.first) continue;
                for(size_t i=0; i<G[v].size(); i++) {
                    auto& e = G[v][i];
                    if(e.cap > 0 and dist[e.to] > dist[v] + e.cost + pot[v] - pot[e.to]) {
                        dist[e.to] = dist[v] + e.cost + pot[v] - pot[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        que.push(make_pair(dist[e.to], e.to));
                    }
                }
            }
            if(dist[t] == IO) {
                return NIL;
            }
            for(int v=0; v<(int)G.size(); v++) pot[v] += dist[v];

            CapTp d = f;
            for(int v=t; v!=s; v=prevv[v]) {
                d = min(d, G[prevv[v]][preve[v]].cap);
            }
            f -= d;
            res += d * pot[t];
            for(int v=t; v!=s; v=prevv[v]) {
                auto& e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return res;
    }    
};

template <typename cap_tp=int, typename cost_tp=int,
          template<typename, typename> class flow_fw=Flow>
struct GeneralizedMincostFlow {
private:
    flow_fw<cap_tp, cost_tp> fl;
    vector<cap_tp> D;
    int N, source, sink;
    cap_tp Z_cap;
    cost_tp Z_cost, ofs, ng;
    int edge_id;

public:
    GeneralizedMincostFlow(int N_,
                           cost_tp ng_=-1,
                           cap_tp IA=1<<29, cost_tp IO=1<<29,
                           cap_tp zero_cap=0, cost_tp zero_cost=0)
        : fl(N_+2, IA, IO, ng_), D(N_), N(N_), source(N_), sink(N_+1),
          Z_cap(zero_cap), Z_cost(zero_cost), ofs(zero_cost), ng(ng_),
          edge_id(0) {}

    int add_edge(int u, int v, cap_tp low, cap_tp high, cost_tp cost) {
        assert(low <= high);
        if(low < Z_cap) {
            add_edge(v, u, -low, -low, -cost);
            add_edge(u, v, 0, high - low, +cost);
            return -1; // TODO ?
        }
        int id = -1;
        
        // コストが負の場合
        if(cost < Z_cost) {
            // 流すだけ得なので high 流れたことにする
            ofs += high * cost;
            D[u] -= high; D[v] += high;
            // 目一杯流したのを high - low 分だけキャンセル可能
            if(high - low > Z_cap) {
                id = edge_id++;
                fl.add_edge(v, u, high - low, -cost);
            }
        }
        else {
            // v 側に low 流れたことにする
            ofs += low * cost;
            D[u] -= low; D[v] += low;
            // high - low 分の辺を張る
            if(high - low > Z_cap) {
                id = edge_id++;
                fl.add_edge(u, v, high - low, cost);
            }
        }
        return id;
    }
    int add_edge(int u, int v, cap_tp cap, cost_tp cost) {
        return add_edge(u, v, Z_cap, cap, cost);
    }
    void change_d(int u, cap_tp delta) {
        D[u] += delta;
    }
    
    cost_tp mincost_flow() {
        cap_tp sum_d = 0;
        for(int i=0; i<N; i++) {
            if(D[i] > 0) {
                fl.add_edge(source, i, D[i], 0);
                sum_d += D[i];
            }
            else {
                fl.add_edge(i, sink, -D[i], 0);
            }
        }

        cost_tp res = fl.fast_mincost_flow(source, sink, sum_d);
        if(res == fl.NIL) return ng;
        else return ofs + res;
    }

    cap_tp get_flowed_cap(size_t k) {
        return fl.get_flowed_cap(k);
    }

    cap_tp operator[](size_t k) {
        return fl.pot[k];
    }
};

int main() {
    ll N, M, X; scanf("%lld%lld%lld", &N, &M, &X);
    vector<ll> a(N), b(N), p(N);
    ll ofs = 0;
    for(int i=0; i<N; i++) {
        scanf("%lld%lld%lld", &a[i], &b[i], &p[i]);
        ofs += a[i] * p[i];
    }
    vector<ll> u(M), v(M), f(M);
    for(int i=0; i<M; i++) {
        scanf("%lld%lld%lld", &u[i], &v[i], &f[i]);
        u[i]--; v[i]--;
    }

    auto s = [](int k) { return k<<1; };
    auto e = [](int k) { return k<<1|1; };

    auto calc = [&a, &b, &p](ll i, ll t) {
        ll res = 0;
        res += ll(1) * min(t, p[i]) * a[i];
        res += ll(1) * max(ll(0), t - p[i]) * b[i];
        return res;
    };
    
    using flow_tp = ll;
    const flow_tp INF = 1LL << 40;
    const flow_tp LONGINF = 1LL << 60;

    ll LIM = 2LL * (N*N*100 + X);
    flow_tp ub = LIM, lb = -1;
    while(ub - lb > 1) {
        flow_tp mid = (ub + lb) / 2;
        GeneralizedMincostFlow<flow_tp, flow_tp> fl(2*N + 1, -INF, +LONGINF, +LONGINF);
        int z = 2*N; // additional variable
        for(int i=0; i<N; i++) {
            fl.add_edge(s(i), z, 0, +INF, 0);
            fl.add_edge(e(i), s(i), 0, +INF, -1);
            fl.add_edge(z, e(i), 0, +INF, mid);
            fl.add_edge(e(i), s(i), b[i], a[i], -p[i]);
        }
        for(int i=0; i+1<N; i++) {
            fl.add_edge(s(i+1), s(i), 0, +INF, 0);
        }
        for(int i=0; i<M; i++) {
            if(f[i] == +1) {
                fl.add_edge(e(u[i]), s(v[i]), 0, +INF, -1);
            }
            if(f[i] == -1) {
                fl.add_edge(s(v[i]), e(u[i]), 0, +INF, 0);
            }        
        }

        flow_tp result = fl.mincost_flow();
        if(result + ofs < X) lb = mid;
        else ub = mid;
    }

    if(ub == LIM) puts("-1");
    else cout << ub << endl;
    return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 3676
final_rank: 7

code_snippet: #include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <cmath>
#include <bitset>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
#include <complex>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <cassert>
#include <fstream>
#include <utility>
#include <functional>
#include <time.h>
#include <stack>
#include <array>
#include <list>
#define popcount __builtin_popcount
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
template<typename Flow, typename Cost>
struct MinCostFlow{
	struct edge{
		int to, rev;
		int num;
		Flow flow;
		Flow cap;
		Cost cost;
		edge(int to, Flow flow, Flow cap, Cost cost, int rev, int num):to(to), flow(flow), cap(cap), cost(cost), rev(rev), num(num){}
	};
	int n;
	vector<vector<edge>> g;
	vector<Flow> b;
	vector<Cost> h, dist;
	vector<int> prevv, preve;
	MinCostFlow(int n):n(n), b(n), g(n), h(n), dist(n), prevv(n), preve(n){}
	void add_edge(int from, int to, Flow lower, Flow upper, Cost cost, int num){
		int num1=g[to].size(), num2=g[from].size();
		if(to==from) num1++;
		g[from].push_back(edge(to, lower, upper, cost, num1, num));
		g[to].push_back(edge(from, -lower, -lower, -cost, num2, -num));
		b[from]-=lower;
		b[to]+=lower;
	}
	Flow mx;
	bool dual(){
		using P=pair<Cost, int>;
		priority_queue<P, vector<P>, greater<P>> que;
		const Cost INF=1e18;
		fill(dist.begin(), dist.end(), INF);
		fill(prevv.begin(), prevv.end(), -1);
		for(int x=0; x<n; x++){
			if(b[x]>0){
				que.push({0, x});
				dist[x]=0;
			}
		}
		mx=0;
		int cnt=0;
		while(!que.empty()){
			auto p=que.top(); que.pop();
			int x=p.second;
			if(dist[x]<p.first) continue;
			mx=max(mx, dist[x]);
			if(b[x]<0) cnt++;
			for(int i=0; i<g[x].size(); i++){
				edge e=g[x][i];
				if(e.cap-e.flow==0) continue;
				int y=e.to;
				if(dist[y]>dist[x]+e.cost+h[x]-h[y]){
					dist[y]=dist[x]+e.cost+h[x]-h[y];
					que.push({dist[y], y});
					prevv[y]=x;
					preve[y]=i;
				}
			}
		}
		if(cnt==0) return false;
		for(int x=0; x<n; x++){
			h[x]+=min(dist[x], mx);
		}
		return true;
	}
	void primal(){
		for(int x=0; x<n; x++){
			if(!(b[x]<0)) continue;
			if(dist[x]>mx) continue;
			Flow f=-b[x];
			int v;
			for(v=x; prevv[v]!=-1; v=prevv[v]){
				edge &e=g[prevv[v]][preve[v]];
				f=min(f, e.cap-e.flow);
			}
			f=min(f, b[v]);
			if(f==0) continue;
			for(v=x; prevv[v]!=-1; v=prevv[v]){
				edge &e=g[prevv[v]][preve[v]];
				e.flow+=f;
				g[v][e.rev].flow-=f;
			}
			b[v]-=f;
			b[x]+=f;
		}
	}
	bool solve(){
		for(int x=0; x<n; x++){
			for(auto &e:g[x]){
				if(e.cost<0 && e.cap-e.flow>0){
					b[x]-=(e.cap-e.flow);
					b[e.to]+=(e.cap-e.flow);
					g[e.to][e.rev].flow-=(e.cap-e.flow);
					e.flow=e.cap;
				}
			}
		}
		while(dual()) primal();
		for(int x=0; x<n; x++){
			if(b[x]!=0) return false;
		}
		return true;
	}
	template<typename T>
	T calc(){
		T ans=0;
		for(int x=0; x<n; x++){
			for(auto e:g[x]){
				ans+=T(e.flow)*T(e.cost);
			}
		}
		ans/=2;
		return ans;
	}
};
int main()
{
	int n, m; ll x;
    cin>>n>>m>>x;
    int a[101], b[101];
    ll p[101];
    for(int i=0; i<n; i++){
        cin>>a[i]>>b[i]>>p[i];
    }
    int u[202], v[202], f[202];
    for(int i=0; i<m; i++){
        cin>>u[i]>>v[i]>>f[i];
        u[i]--; v[i]--;
    }
    const ll mx=1e9;
    ll tl=0, tr=mx;
    while(tr-tl>1){
        ll t=(tl+tr)/2;
        MinCostFlow<ll, ll> mcf(2*n);
        const ll INF=1e12;
        for(int i=0; i<n; i++){
            mcf.b[i]+=a[i];
            mcf.b[i+n]-=a[i];
        }
        for(int i=0; i<n; i++){
            mcf.add_edge(i, i+n, 0, a[i]-b[i], p[i], 0);
            mcf.add_edge(0, i+n, 0, INF, t, 0);
            mcf.add_edge(i+n, i, 0, INF, -1, 0);
        }
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                mcf.add_edge(j, i, 0, INF, 0, 0);
            }
        }
        for(int i=0; i<m; i++){
            if(f[i]==1){
                mcf.add_edge(u[i]+n, v[i], 0, INF, -1, 0);
            }else{
                mcf.add_edge(v[i], u[i]+n, 0, INF, 0, 0);
            }
        }
        mcf.solve();
        ll res=mcf.calc<ll>();
        if(res>=x) tr=t;
        else tl=t;
    }
    if(tr==mx) cout<<-1<<endl;
    else cout<<tr<<endl;
	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 3860
final_rank: 10

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

using namespace std;

using int64 = long long;
const int mod = 1e9 + 7;
// const int mod = 998244353;

const int64 infll = (1LL << 62) - 1;
//const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

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 T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

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

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}


template< typename flow_t, typename cost_t >
struct edge {
  int src, to;
  flow_t low, high;
  cost_t cost;

  edge() = default;

  edge(int src, int to, flow_t high, cost_t cost) : src(src), to(to), low(0), high(high), cost(cost) {}

  edge(int src, int to, flow_t low, flow_t high, cost_t cost) : src(src), to(to), low(low), high(high), cost(cost) {}
};


template< typename flow_t, typename cost_t, template< typename, typename > class MF >
cost_t normalized_min_cost_flow(vector< flow_t > D, const vector< edge< flow_t, cost_t > > &E, cost_t NG = -1) {
  const int N = (int) D.size(), M = (int) E.size();
  MF< flow_t, cost_t > flow(N + 2);
  const int S = N, T = N + 1;

  cost_t sum = 0;
  for(auto &e : E) {
    if(e.cost < 0) {
      sum += e.cost * e.high;
      D[e.src] -= e.high;
      D[e.to] += e.high;
      flow.add_edge(e.to, e.src, e.high - e.low, -e.cost);
    } else {
      sum += e.cost * e.low;
      D[e.src] -= e.low;
      D[e.to] += e.low;
      flow.add_edge(e.src, e.to, e.high - e.low, e.cost);
    }
  }

  flow_t in = 0;
  for(int i = 0; i < N; i++) {
    if(D[i] > 0) {
      flow.add_edge(S, i, D[i], flow_t(0));
      in += D[i];
    } else if(D[i] < 0) {
      flow.add_edge(i, T, -D[i], flow_t(0));
    }
  }

  auto ret = flow.min_cost_flow(S, T, in);
  if(ret == -1) return NG;
  return ret + sum;
}

template< typename flow_t, typename cost_t >
struct PrimalDual {
  const cost_t INF;

  struct edge {
    int to;
    flow_t cap;
    cost_t cost;
    int rev;
    bool isrev;
  };
  vector< vector< edge > > graph;
  vector< cost_t > potential, min_cost;
  vector< int > prevv, preve;

  PrimalDual(int V) : graph(V), INF(numeric_limits< cost_t >::max()) {}

  void add_edge(int from, int to, flow_t cap, cost_t cost) {
    graph[from].emplace_back((edge) {to, cap, cost, (int) graph[to].size(), false});
    graph[to].emplace_back((edge) {from, 0, -cost, (int) graph[from].size() - 1, true});
  }

  cost_t min_cost_flow(int s, int t, flow_t f) {
    int V = (int) graph.size();
    cost_t ret = 0;
    using Pi = pair< cost_t, int >;
    priority_queue< Pi, vector< Pi >, greater< Pi > > que;
    potential.assign(V, 0);
    preve.assign(V, -1);
    prevv.assign(V, -1);

    while(f > 0) {
      min_cost.assign(V, INF);
      que.emplace(0, s);
      min_cost[s] = 0;
      while(!que.empty()) {
        Pi p = que.top();
        que.pop();
        if(min_cost[p.second] < p.first) continue;
        for(int i = 0; i < graph[p.second].size(); i++) {
          edge &e = graph[p.second][i];
          cost_t nextCost = min_cost[p.second] + e.cost + potential[p.second] - potential[e.to];
          if(e.cap > 0 && min_cost[e.to] > nextCost) {
            min_cost[e.to] = nextCost;
            prevv[e.to] = p.second, preve[e.to] = i;
            que.emplace(min_cost[e.to], e.to);
          }
        }
      }
      if(min_cost[t] == INF) return -1;
      for(int v = 0; v < V; v++) potential[v] += min_cost[v];
      flow_t addflow = f;
      for(int v = t; v != s; v = prevv[v]) {
        addflow = min(addflow, graph[prevv[v]][preve[v]].cap);
      }
      f -= addflow;
      ret += addflow * potential[t];
      for(int v = t; v != s; v = prevv[v]) {
        edge &e = graph[prevv[v]][preve[v]];
        e.cap -= addflow;
        graph[v][e.rev].cap += addflow;
      }
    }
    return ret;
  }

  void output() {
    for(int i = 0; i < graph.size(); i++) {
      for(auto &e : graph[i]) {
        if(e.isrev) continue;
        auto &rev_e = graph[e.to][e.rev];
        cout << i << "->" << e.to << " (flow: " << rev_e.cap << "/" << rev_e.cap + e.cap << ")" << endl;
      }
    }
  }
};

int main() {
  int N, M, X;
  cin >> N >> M >> X;
  vector< int > A(N), B(N), P(N);
  for(int i = 0; i < N; i++) {
    cin >> A[i] >> B[i] >> P[i];
  }
  vector< int > U(M), V(M), F(M);
  for(int i = 0; i < M; i++) {
    cin >> U[i] >> V[i] >> F[i];
    --U[i], --V[i];
  }

  using flow_t = int64;
  using cost_t = int64;
  cost_t inf = 1e15;

  auto check = [&](int Y) {
    vector< flow_t > D(N + N + 1);
    int Z = N + N;
    vector< edge< flow_t, cost_t > > E;
    for(int i = 0; i < N; i++) {
      E.emplace_back(i, Z, 0, inf, 0);
      E.emplace_back(i + N, i, inf, -1);
      E.emplace_back(Z, i + N, inf, Y);
      if(i + 1 < N) E.emplace_back(i + 1, i, inf, 0);
    }
    for(int i = 0; i < M; i++) {
      if(F[i] == 1) E.emplace_back(U[i] + N, V[i], inf, -1);
      else E.emplace_back(V[i], U[i] + N, inf, 0);
    }
    for(int i = 0; i < N; i++) {
      E.emplace_back(i, i + N, A[i] - B[i], P[i]);
      if(A[i] >= 0) {
        D[i + N] -= A[i];
        D[i] += A[i];
        E.emplace_back(i + N, i, inf, 0);
      } else {
        E.emplace_back(i, i + N, -A[i], 0);
      }
    }
    return normalized_min_cost_flow< flow_t, cost_t, PrimalDual >(D, E);
  };
  int ok = 1e9, ng = -1;
  if(check(ok) < X) {
    cout << -1 << "\n";
    exit(0);
  }
  while(ok - ng > 1) {
    int mid = (ok + ng) / 2;
    if(check(mid) >= X) ok = mid;
    else ng = mid;
  }
  cout << ok << "\n";
}
accuracy: 1
time_ms: 360
memory_kb: 3368
final_rank: 6

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<math.h>
#include<complex>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<functional>
#include<assert.h>
#include<numeric>
using namespace std;
#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )
#define rep(i,n) REP(i,0,n)
using ll = long long;
constexpr ll mod=2e8+7 ;

struct PrimalDual{
    struct edge{
        int to;ll cap, cost;int rev;
    };
    int n;
    const ll INF = numeric_limits<ll>::max();
    vector<vector<edge>> v;
    vector<ll> pot, dist;
    vector<pair<int,int>> par;
 
    PrimalDual(int n):n(n),v(n),pot(n){}
 
    void add_edge(int from, int to, ll cap, ll cost) {
        v[from].emplace_back((edge) {to, cap, cost, (int) v[to].size()});
        v[to].emplace_back((edge) {from, 0, -cost, (int) v[from].size() - 1});
    }
 
    pair<ll,ll> minimum_road(int s,int t){
        par.assign(n,{-1,-1});
        dist.assign(n,INF);
        dist[s] = 0;
        using P = pair<ll,ll>;
        priority_queue<P,vector<P>,greater<P>> pq;
        pq.emplace(0,s);
        while(!pq.empty()){
            P p = pq.top();pq.pop();
            if(dist[p.second]<p.first)continue;
            rep(i,v[p.second].size()){
                edge& e = v[p.second][i];
                ll nd = dist[p.second]+e.cost+pot[p.second]-pot[e.to];
                if(e.cap>0 && dist[e.to]>nd){
                    dist[e.to] = nd;
                    par[e.to] = {p.second, i};
                    pq.emplace(dist[e.to],e.to);
                }
            }
        }
        if(dist[t]==INF)return {-1,-1};
        rep(i,n)pot[i] += dist[i];
        ll f = INF;
        int cur = t;
        while(cur != s){
            int p = par[cur].first, j = par[cur].second;
            f = min(f, v[p][j].cap);
            cur = p;
        }
        cur = t;
        while(cur != s){
            int p = par[cur].first, j = par[cur].second;
            v[p][j].cap -= f;
            v[cur][v[p][j].rev].cap += f;
            cur = p;
        }
        return {pot[t],f};
    }
 
    ll minimum_cost_flow(int s, int t, ll k){
        ll ret = 0;
        while(k){
            pair<ll,ll> z = minimum_road(s, t);
            if (z.first < 0)return -1;
            if (k<=z.second){
                ret+=z.first*k;
                break;
            }
            k -= z.second;
            ret += z.first*z.second;
        }
        return ret;
    }
};

int main(){
    int n,m,x;
    cin>>n>>m>>x;
    vector<int> a(n),b(n),p(n);
    rep(i,n)cin>>a[i]>>b[i]>>p[i];
    vector<int> f(m),u(m),v(m);
    rep(i,m){
        cin>>u[i]>>v[i]>>f[i];
        --u[i];--v[i];
        if(u[i]<v[i])swap(u[i],v[i]);
    }
    ll ng = -1, ok = 2e8;
    while(ok-ng>1){
        int mid = (ok+ng)/2;
        PrimalDual pd(3*n+3);
        int s0=3*n, S = 3*n+1, T = 3*n+2;
        vector<ll> cost(3*n+3);
        rep(i,n){
            cost[3*i+0]+=a[i];
            cost[3*i+1]+=b[i]-a[i];
            cost[3*i+2]+=-b[i];
        }
        ll ret = 0;
        rep(i,n){
            pd.add_edge(3*i+2, 3*i+1, 2e8, 0);
            cost[3*i+0]+=2e8;
            cost[3*i+1]-=2e8;
            ret-=2e8;
            pd.add_edge(3*i+0, 3*i+1, 2e8, 1);
            pd.add_edge(3*i+0, 3*i+1, 2e8, p[i]);
            pd.add_edge(s0, 3*i+2, 2e8, mid);
        }
        rep(i,n-1){
            pd.add_edge(3*i+3, 3*i+0, 2e8, 0);
        }
        pd.add_edge(0, s0, 2e8, 0);
        rep(i,m){
            if(f[i]==1){
                ret += -2e8;
                cost[3*v[i]+2]-=2e8;
                cost[3*u[i]+0]+=2e8;
                pd.add_edge(3*u[i]+0, 3*v[i]+2, 2e8, 1);
            } else {
                pd.add_edge(3*u[i]+0, 3*v[i]+2, 2e8, 0);
            }
        }
        ll sum = 0;
        rep(i,3*n+1){
            if(cost[i]>0){
                pd.add_edge(S, i, cost[i], 0);
                sum += cost[i];
            } else {
                pd.add_edge(i, T, -cost[i], 0);
            }
        }
        ll ans = pd.minimum_cost_flow(S, T, sum)+ret;
        if(ans>=x)ok=mid;
        else ng = mid;
    }
    if(ok >= x + 1000000){
        cout<<-1<<endl;
    } else {
        cout << ok << endl;
    }

    
    return 0;
}
accuracy: 1
time_ms: 510
memory_kb: 3524
final_rank: 9

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<math.h>
#include<complex>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<functional>
#include<assert.h>
#include<numeric>
using namespace std;
#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )
#define rep(i,n) REP(i,0,n)
using ll = long long;
constexpr ll mod=1e8+7 ;

struct PrimalDual{
    struct edge{
        int to;ll cap, cost;int rev;
    };
    int n;
    const ll INF = numeric_limits<ll>::max();
    vector<vector<edge>> v;
    vector<ll> pot, dist;
    vector<pair<int,int>> par;
 
    PrimalDual(int n):n(n),v(n),pot(n){}
 
    void add_edge(int from, int to, ll cap, ll cost) {
        v[from].emplace_back((edge) {to, cap, cost, (int) v[to].size()});
        v[to].emplace_back((edge) {from, 0, -cost, (int) v[from].size() - 1});
    }
 
    pair<ll,ll> minimum_road(int s,int t){
        par.assign(n,{-1,-1});
        dist.assign(n,INF);
        dist[s] = 0;
        using P = pair<ll,ll>;
        priority_queue<P,vector<P>,greater<P>> pq;
        pq.emplace(0,s);
        while(!pq.empty()){
            P p = pq.top();pq.pop();
            if(dist[p.second]<p.first)continue;
            rep(i,v[p.second].size()){
                edge& e = v[p.second][i];
                ll nd = dist[p.second]+e.cost+pot[p.second]-pot[e.to];
                if(e.cap>0 && dist[e.to]>nd){
                    dist[e.to] = nd;
                    par[e.to] = {p.second, i};
                    pq.emplace(dist[e.to],e.to);
                }
            }
        }
        if(dist[t]==INF)return {-1,-1};
        rep(i,n)pot[i] += dist[i];
        ll f = INF;
        int cur = t;
        while(cur != s){
            int p = par[cur].first, j = par[cur].second;
            f = min(f, v[p][j].cap);
            cur = p;
        }
        cur = t;
        while(cur != s){
            int p = par[cur].first, j = par[cur].second;
            v[p][j].cap -= f;
            v[cur][v[p][j].rev].cap += f;
            cur = p;
        }
        return {pot[t],f};
    }
 
    ll minimum_cost_flow(int s, int t, ll k){
        ll ret = 0;
        while(k){
            pair<ll,ll> z = minimum_road(s, t);
            if (z.first < 0)return -1;
            if (k<=z.second){
                ret+=z.first*k;
                break;
            }
            k -= z.second;
            ret += z.first*z.second;
        }
        return ret;
    }
};

int main(){
    int n,m,x;
    cin>>n>>m>>x;
    vector<int> a(n),b(n),p(n);
    rep(i,n)cin>>a[i]>>b[i]>>p[i];
    vector<int> f(m),u(m),v(m);
    rep(i,m){
        cin>>u[i]>>v[i]>>f[i];
        --u[i];--v[i];
        if(u[i]<v[i])swap(u[i],v[i]);
    }
    ll ng = -1, ok = 1e8;
    while(ok-ng>1){
        int mid = (ok+ng)/2;
        PrimalDual pd(3*n+3);
        int s0=3*n, S = 3*n+1, T = 3*n+2;
        vector<ll> cost(3*n+3);
        rep(i,n){
            cost[3*i+0]+=a[i];
            cost[3*i+1]+=b[i]-a[i];
            cost[3*i+2]+=-b[i];
        }
        ll ret = 0;
        rep(i,n){
            pd.add_edge(3*i+2, 3*i+1, 1e8, 0);
            cost[3*i+0]+=1e8;
            cost[3*i+1]-=1e8;
            ret-=1e8;
            pd.add_edge(3*i+0, 3*i+1, 1e8, 1);
            pd.add_edge(3*i+0, 3*i+1, 1e8, p[i]);
            pd.add_edge(s0, 3*i+2, 1e8, mid);
        }
        rep(i,n-1){
            pd.add_edge(3*i+3, 3*i+0, 1e8, 0);
        }
        pd.add_edge(0, s0, 1e8, 0);
        rep(i,m){
            if(f[i]==1){
                ret += -1e8;
                cost[3*v[i]+2]-=1e8;
                cost[3*u[i]+0]+=1e8;
                pd.add_edge(3*u[i]+0, 3*v[i]+2, 1e8, 1);
            } else {
                pd.add_edge(3*u[i]+0, 3*v[i]+2, 1e8, 0);
            }
        }
        ll sum = 0;
        rep(i,3*n+1){
            if(cost[i]>0){
                pd.add_edge(S, i, cost[i], 0);
                sum += cost[i];
            } else {
                pd.add_edge(i, T, -cost[i], 0);
            }
        }
        ll ans = pd.minimum_cost_flow(S, T, sum)+ret;
        if(ans>=x)ok=mid;
        else ng = mid;
    }
    if(ok >= x + 100000){
        cout<<-1<<endl;
    } else {
        cout << ok << endl;
    }
    return 0;
}
accuracy: 0.6888888888888889
time_ms: 470
memory_kb: 3568
final_rank: 11

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<math.h>
#include<complex>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<functional>
#include<assert.h>
#include<numeric>
using namespace std;
#define REP(i,m,n) for(int i=(int)(m) ; i < (int) (n) ; ++i )
#define rep(i,n) REP(i,0,n)
using ll = long long;
constexpr ll mod=1e7+7 ;

struct PrimalDual{
    struct edge{
        int to;ll cap, cost;int rev;
    };
    int n;
    const ll INF = numeric_limits<ll>::max();
    vector<vector<edge>> v;
    vector<ll> pot, dist;
    vector<pair<int,int>> par;
 
    PrimalDual(int n):n(n),v(n),pot(n){}
 
    void add_edge(int from, int to, ll cap, ll cost) {
        v[from].emplace_back((edge) {to, cap, cost, (int) v[to].size()});
        v[to].emplace_back((edge) {from, 0, -cost, (int) v[from].size() - 1});
    }
 
    pair<ll,ll> minimum_road(int s,int t){
        par.assign(n,{-1,-1});
        dist.assign(n,INF);
        dist[s] = 0;
        using P = pair<ll,ll>;
        priority_queue<P,vector<P>,greater<P>> pq;
        pq.emplace(0,s);
        while(!pq.empty()){
            P p = pq.top();pq.pop();
            if(dist[p.second]<p.first)continue;
            rep(i,v[p.second].size()){
                edge& e = v[p.second][i];
                ll nd = dist[p.second]+e.cost+pot[p.second]-pot[e.to];
                if(e.cap>0 && dist[e.to]>nd){
                    dist[e.to] = nd;
                    par[e.to] = {p.second, i};
                    pq.emplace(dist[e.to],e.to);
                }
            }
        }
        if(dist[t]==INF)return {-1,-1};
        rep(i,n)pot[i] += dist[i];
        ll f = INF;
        int cur = t;
        while(cur != s){
            int p = par[cur].first, j = par[cur].second;
            f = min(f, v[p][j].cap);
            cur = p;
        }
        cur = t;
        while(cur != s){
            int p = par[cur].first, j = par[cur].second;
            v[p][j].cap -= f;
            v[cur][v[p][j].rev].cap += f;
            cur = p;
        }
        return {pot[t],f};
    }
 
    ll minimum_cost_flow(int s, int t, ll k){
        ll ret = 0;
        while(k){
            pair<ll,ll> z = minimum_road(s, t);
            if (z.first < 0)return -1;
            if (k<=z.second){
                ret+=z.first*k;
                break;
            }
            k -= z.second;
            ret += z.first*z.second;
        }
        return ret;
    }
};

int main(){
    int n,m,x;
    cin>>n>>m>>x;
    vector<int> a(n),b(n),p(n);
    rep(i,n)cin>>a[i]>>b[i]>>p[i];
    vector<int> f(m),u(m),v(m);
    rep(i,m){
        cin>>u[i]>>v[i]>>f[i];
        --u[i];--v[i];
        if(u[i]<v[i])swap(u[i],v[i]);
    }
    ll ng = -1, ok = 1e7;
    while(ok-ng>1){
        int mid = (ok+ng)/2;
        PrimalDual pd(3*n+3);
        int s0=3*n, S = 3*n+1, T = 3*n+2;
        vector<ll> cost(3*n+3);
        rep(i,n){
            cost[3*i+0]+=a[i];
            cost[3*i+1]+=b[i]-a[i];
            cost[3*i+2]+=-b[i];
        }
        ll ret = 0;
        rep(i,n){
            pd.add_edge(3*i+2, 3*i+1, 1e7, 0);
            cost[3*i+0]+=1e7;
            cost[3*i+1]-=1e7;
            ret-=1e7;
            pd.add_edge(3*i+0, 3*i+1, 1e7, 1);
            pd.add_edge(3*i+0, 3*i+1, 1e7, p[i]);
            pd.add_edge(s0, 3*i+2, 1e7, mid);
        }
        rep(i,n-1){
            pd.add_edge(3*i+3, 3*i+0, 1e7, 0);
        }
        pd.add_edge(0, s0, 1e7, 0);
        rep(i,m){
            if(f[i]==1){
                ret += -1e7;
                cost[3*v[i]+2]-=1e7;
                cost[3*u[i]+0]+=1e7;
                pd.add_edge(3*u[i]+0, 3*v[i]+2, 1e7, 1);
            } else {
                pd.add_edge(3*u[i]+0, 3*v[i]+2, 1e7, 0);
            }
        }
        ll sum = 0;
        rep(i,3*n+1){
            if(cost[i]>0){
                pd.add_edge(S, i, cost[i], 0);
                sum += cost[i];
            } else {
                pd.add_edge(i, T, -cost[i], 0);
            }
        }
        ll ans = pd.minimum_cost_flow(S, T, sum)+ret;
        if(ans>=x)ok=mid;
        else ng = mid;
    }
    if(ok >= x + 100000){
        cout<<-1<<endl;
    } else {
        cout << ok << endl;
    }

    
    return 0;
}
accuracy: 0.13333333333333333
time_ms: 10
memory_kb: 3364
final_rank: 19

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

using Int = long long;
const char newl = '\n';

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
template<typename T> void drop(const T &x){cout<<x<<endl;exit(0);}
template<typename T=Int>
vector<T> read(size_t n){
  vector<T> ts(n);
  for(size_t i=0;i<n;i++) cin>>ts[i];
  return ts;
}


template<typename TF,typename TC>
struct PrimalDual{
  struct edge{
    Int to;
    TF cap;
    TC cost;
    Int rev;
    edge(){}
    edge(Int to,TF cap,TC cost,Int rev):
      to(to),cap(cap),cost(cost),rev(rev){}
  };

  static const TC INF;
  vector<vector<edge>> G;
  vector<TC> h,dist;
  vector<Int> prevv,preve;

  PrimalDual(){}
  PrimalDual(Int n):G(n),h(n),dist(n),prevv(n),preve(n){}

  void add_edge(Int u,Int v,TF cap,TC cost){
    G[u].emplace_back(v,cap,cost,G[v].size());
    G[v].emplace_back(u,0,-cost,G[u].size()-1);
  }

  void dijkstra(Int s){
    struct P{
      TC first;
      Int second;
      P(TC first,Int second):first(first),second(second){}
      bool operator<(const P&a) const{return a.first<first;}
    };
    priority_queue<P> que;
    fill(dist.begin(),dist.end(),INF);

    dist[s]=0;
    que.emplace(dist[s],s);
    while(!que.empty()){
      P p=que.top();que.pop();
      Int v=p.second;
      if(dist[v]<p.first) continue;
      for(Int i=0;i<(Int)G[v].size();i++){
        edge &e=G[v][i];
        if(e.cap==0) continue;
        if(dist[v]+e.cost+h[v]-h[e.to]<dist[e.to]){
          dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
          prevv[e.to]=v;
          preve[e.to]=i;
          que.emplace(dist[e.to],e.to);
        }
      }
    }
  }

  TC flow(Int s,Int t,TF f,Int &ok){
    TC res=0;
    fill(h.begin(),h.end(),0);
    while(f>0){
      dijkstra(s);
      if(dist[t]==INF){
        ok=0;
        return res;
      }

      for(Int v=0;v<(Int)h.size();v++)
        if(dist[v]<INF) h[v]=h[v]+dist[v];

      TF d=f;
      for(Int v=t;v!=s;v=prevv[v])
        d=min(d,G[prevv[v]][preve[v]].cap);

      f-=d;
      res=res+h[t]*d;
      for(Int v=t;v!=s;v=prevv[v]){
        edge &e=G[prevv[v]][preve[v]];
        e.cap-=d;
        G[v][e.rev].cap+=d;
      }
    }
    ok=1;
    return res;
  }
};
template<typename TF, typename TC>
const TC PrimalDual<TF, TC>::INF = numeric_limits<TC>::max()/2;


template<typename TF,typename TC>
struct NegativeEdge{
  PrimalDual<TF, TC> G;
  vector<TF> fs;
  TC sum;
  Int S,T;
  NegativeEdge(){}
  NegativeEdge(Int n):G(n+2),fs(n+2,0),sum(0),S(n),T(n+1){}

  void use_edge(Int u,Int v,TF cap,TC cost){
    fs[u]-=cap;
    fs[v]+=cap;
    sum=sum+cost*cap;
  }

  void add_edge(Int u,Int v,TF cap,TC cost){
    if(cost<TC(0)){
      use_edge(u,v,cap,cost);
      swap(u,v);
      cost=-cost;
    }
    G.add_edge(u,v,cap,cost);
  }

  TC flow(Int &ok){
    TF f=0;
    for(Int i=0;i<S;i++){
      if(fs[i]>0){
        f+=fs[i];
        G.add_edge(S,i,+fs[i],TC(0));
      }
      if(fs[i]<0){
        G.add_edge(i,T,-fs[i],TC(0));
      }
    }
    return sum+G.flow(S,T,f,ok);
  }

  TC flow(Int ts,Int tt,TF tf,Int &ok){
    fs[ts]+=tf;
    fs[tt]-=tf;
    return flow(ok);
  }
};


template<typename TV, const Int N> void read_tuple_impl(TV&) {}
template<typename TV, const Int N, typename Head, typename... Tail>
void read_tuple_impl(TV& ts) {
  get<N>(ts).emplace_back(*(istream_iterator<Head>(cin)));
  read_tuple_impl<TV, N+1, Tail...>(ts);
}
template<typename... Ts> decltype(auto) read_tuple(size_t n) {
  tuple<vector<Ts>...> ts;
  for(size_t i=0;i<n;i++) read_tuple_impl<decltype(ts), 0, Ts...>(ts);
  return ts;
}

//INSERT ABOVE HERE
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(0);

  Int n,m,need;
  cin>>n>>m>>need;
  auto [xs,ys,qs]=read_tuple<Int, Int, Int>(n);
  auto [us,vs,fs]=read_tuple<Int, Int, Int>(m);

  for(Int i=0;i<m;i++) us[i]--,vs[i]--;

  const Int INF = 1e15;
  auto st=[&](Int i){return 0+i;};
  auto en=[&](Int i){return n+i;};
  Int Z=n+n;
  auto check=[&](Int T)->Int{
    NegativeEdge<Int, Int> G(n+n+1);
    for(Int i=0;i<n;i++){
      G.add_edge(st(i),Z,INF,0);
      G.add_edge(en(i),st(i),INF,-1);
      G.add_edge(Z,en(i),INF,T);
    }
    for(Int i=0;i<m;i++){
      if(fs[i]==+1)
        G.add_edge(en(us[i]),st(vs[i]),INF,-1);
      if(fs[i]==-1)
        G.add_edge(st(vs[i]),en(us[i]),INF,0);
    }
    for(Int i=0;i+1<n;i++)
      G.add_edge(st(i+1),st(i),INF,0);

    for(Int i=0;i<n;i++){
      G.add_edge(st(i),en(i),xs[i]-ys[i],qs[i]);
      if(xs[i]>=0){
        G.use_edge(en(i),st(i),xs[i],0);
        G.add_edge(en(i),st(i),INF,0);
      }else{
        G.add_edge(st(i),en(i),abs(xs[i]),0);
      }
    }
    Int ok;
    Int res=G.flow(ok);
    if(!ok) return -1;
    return res;
  };

  Int L=0,R=1e9;
  // check(L) < need
  // check(R) >= need
  if(check(R)<need) drop(-1);
  while(L+1<R){
    Int M=(L+R)>>1;
    if(check(M)>=need) R=M;
    else L=M;
  }
  // cout<<need<<endl;
  // cout<<check(L)<<endl;
  // cout<<check(R)<<endl;
  cout<<R<<newl;
  return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 3640
final_rank: 8