#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#ifndef rd
#define trace(...)
#define endl '\n'
#endif
#define pb push_back
#define fi first
#define se second
#define int long long
typedef long long ll;
typedef long double f80;
#define double long double
#define pii pair<int,int>
#define pll pair<ll,ll>
#define sz(x) ((long long)x.size())
#define fr(a,b,c) for(int a=b; a<=c; a++)
#define rep(a,b,c) for(int a=b; a<c; a++)
#define trav(a,x) for(auto &a:x)
#define all(con) con.begin(),con.end()
const ll infl=0x3f3f3f3f3f3f3f3fLL;
const int infi=0x3f3f3f3f;
//const int mod=998244353;
const int mod=1000000007;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> oset;
auto clk=clock();
mt19937_64 rang(chrono::high_resolution_clock::now().time_since_epoch().count());
int rng(int lim) {
uniform_int_distribution<int> uid(0,lim-1);
return uid(rang);
}
int powm(int a, int b) {
int res=1;
while(b) {
if(b&1)
res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
long long readInt(long long l, long long r, char endd) {
long long x=0;
int cnt=0;
int fi=-1;
bool is_neg=false;
while(true) {
char g=getchar();
if(g=='-') {
assert(fi==-1);
is_neg=true;
continue;
}
if('0'<=g&&g<='9') {
x*=10;
x+=g-'0';
if(cnt==0) {
fi=g-'0';
}
cnt++;
assert(fi!=0 || cnt==1);
assert(fi!=0 || is_neg==false);
assert(!(cnt>19 || ( cnt==19 && fi>1) ));
} else if(g==endd) {
if(is_neg) {
x=-x;
}
assert(l<=x&&x<=r);
return x;
} else {
assert(false);
}
}
}
string readString(int l, int r, char endd) {
string ret="";
int cnt=0;
while(true) {
char g=getchar();
assert(g!=-1);
if(g==endd) {
break;
}
cnt++;
ret+=g;
}
assert(l<=cnt&&cnt<=r);
return ret;
}
long long readIntSp(long long l, long long r) {
return readInt(l,r,' ');
}
long long readIntLn(long long l, long long r) {
return readInt(l,r,'\n');
}
string readStringLn(int l, int r) {
return readString(l,r,'\n');
}
string readStringSp(int l, int r) {
return readString(l,r,' ');
}
int sum_n=0,sum_m=0,sum_q=0;
#define rsz(x, n) x.resize(n)
#define clr(x) x.clear()
class SCC {
public:
int n,cnt; // cnt -> number of scc's formed
vector<vector<int>> g,rg,sg,comp; // sg -> dag with all nodes compressed.
vector<int> scc,order;
vector<bool> vis;
void reset() {
clr(g),clr(rg),clr(sg),clr(comp),clr(scc),clr(order),clr(vis);
}
void init(int _n) {
reset();
n=_n,cnt=0;
_n+=2;
rsz(g, _n),rsz(rg,_n),rsz(sg,_n),rsz(comp,_n);
scc.resize(_n,0);
vis.resize(_n,0);
}
void add(int u, int v) {
g[u].push_back(v);
rg[v].push_back(u);
}
void compute() {
fr(i, 1, n)
if(!vis[i])
dfs1(i);
fill(all(vis),0);
for(int i=n-1; i>=0; i--)
if(!vis[order[i]])
dfs2(order[i],++cnt);
}
void dfs1(int u) {
vis[u]=1;
for(int v : g[u])
if(!vis[v])
dfs1(v);
order.pb(u);
}
void dfs2(int u, int c) {
vis[u]=1;
scc[u]=c;
comp[c].pb(u);
for(int v : rg[u]) {
if(!vis[v])
dfs2(v,c);
if(vis[v]&&c!=scc[v])
sg[scc[v]].pb(c);
}
}
};
struct Edge {
int from,to,cap,flow,index;
Edge(int from, int to, int cap, int flow, int index) :
from(from), to(to), cap(cap), flow(flow), index(index) {
}
};
struct PushRelabel {
int N;
vector<vector<Edge> > G;
vector<ll> excess;
vector<int> dist,active,count;
queue<int> Q;
PushRelabel(int N) :
N(N), G(N), excess(N), dist(N), active(N), count(2*N) {
}
void AddEdge(int from, int to, int cap) {
G[from].push_back(Edge(from,to,cap,0,G[to].size()));
if(from==to)
G[from].back().index++;
G[to].push_back(Edge(to,from,0,0,G[from].size()-1)); // for bidirectional set cap.
}
void Enqueue(int v) {
if(!active[v]&&excess[v]>0) {
active[v]=true;
Q.push(v);
}
}
void Push(Edge &e) {
int amt=min(excess[e.from],ll(e.cap-e.flow));
if(dist[e.from]<=dist[e.to]||amt==0)
return;
e.flow+=amt;
G[e.to][e.index].flow-=amt;
excess[e.to]+=amt;
excess[e.from]-=amt;
Enqueue(e.to);
}
void Gap(int k) {
fr(v, 0, N - 1) {
if(dist[v]<k)
continue;
count[dist[v]]--;
dist[v]=max(dist[v],N+1);
count[dist[v]]++;
Enqueue(v);
}
}
void Relabel(int v) {
count[dist[v]]--;
dist[v]=2*N;
fr(i, 0, G[v].size() - 1)
if(G[v][i].cap-G[v][i].flow>0)
dist[v]=min(dist[v],dist[G[v][i].to]+1);
count[dist[v]]++;
Enqueue(v);
}
void Discharge(int v) {
for(int i=0; excess[v]>0&&i<G[v].size(); i++)
Push(G[v][i]);
if(excess[v]>0) {
if(count[dist[v]]==1) {
Gap(dist[v]);
}
else
Relabel(v);
}
}
ll GetMaxFlow(int s, int t) {
count[0]=N-1;
count[N]=1;
dist[s]=N;
active[s]=active[t]=1;
fr(i, 0, (int)G[s].size() - 1) {
excess[s]+=G[s][i].cap;
Push(G[s][i]);
}
while(!Q.empty()) {
int v=Q.front();
Q.pop();
active[v]=0;
Discharge(v);
}
ll totflow=0;
fr(i, 0, (int)G[s].size() - 1)
totflow+=G[s][i].flow;
return totflow;
}
};
const int INF=infi;
struct MaxFlowLowerBound {
PushRelabel PR;
int N,s,t,s1,t1;
ll total_demands;
MaxFlowLowerBound(int N, int s, int t) :
N(N), PR(N+2), s(s), t(t), s1(N), t1(N+1), total_demands(0) {
PR.AddEdge(t,s,INF);
}
void AddEdge(int from, int to, ll lo, ll hi) {
PR.AddEdge(s1,to,lo);
PR.AddEdge(from,t1,lo);
PR.AddEdge(from,to,hi-lo);
total_demands+=lo;
}
ll GetMaxFlow() {
if(PR.GetMaxFlow(s1,t1)<total_demands)
return -1;
PushRelabel PR1(N);
ll initial=0;
for(int i=0; i<N; i++) {
for(auto e : PR.G[i]) {
if(e.flow<0||e.cap==0)
continue;
if(e.to>=N)
continue;
if(i==t&&e.to==s) {
initial=e.flow;
continue;
}
PR1.AddEdge(i,e.to,e.cap-e.flow);
PR1.AddEdge(e.to,i,e.flow);
}
}
return initial+PR1.GetMaxFlow(s,t);
}
};
const int N=30005;
int in[N],ut[N],oin[N],out[N];
pii il[N],ul[N];
pii oil[N],oul[N];
void solve() {
int n=readIntSp(1,30000),m=readIntSp(0,30000),q=readIntLn(0,300000);
// int n,m,q;
// cin>>n>>m>>q;
fr(i,1,n) {
oil[i]={0,m};
oul[i]={0,m};
il[i]={0,m};
ul[i]={0,m};
in[i]=ut[i]=oin[i]=out[i]=0;
}
sum_n+=n;
sum_m+=m;
sum_q+=q;
assert(sum_n<=60000&&sum_m<=60000&&sum_q<=600000);
SCC G;
G.init(n);
vector<pii> edg;
fr(i,1,m) {
int u=readIntSp(1,n),v=readIntLn(1,n);
// int u,v;
// cin>>u>>v;
assert(u!=v);
G.add(u,v);
edg.pb({u,v});
}
G.compute();
for(auto e:edg) {
out[e.fi]++;
oin[e.se]++;
ut[G.scc[e.fi]]++;
in[G.scc[e.se]]++;
}
fr(i,1,n) {
oil[i].se=oin[i];
oul[i].se=out[i];
il[i].se=in[i];
ul[i].se=ut[i];
}
int c1=readIntSp(1,1000000000),c2=readIntLn(1,1000000000);
bool swapped=0;
if(c1>c2) {
swapped=1;
swap(c1,c2);
}
int src=2*n+2*G.cnt+1,sink=2*n+2*G.cnt+2;
MaxFlowLowerBound F(2*n+2*G.cnt+5,src,sink);
bool no=0;
fr(i,1,q) {
int t=readIntSp(1,4),w=readIntSp(1,n),x=readIntSp(1,2),l=readIntSp(0,m),r=readIntLn(l,m);
if(G.scc[w]==1&&t<=2) {
trace(t,w,x,l,r,ul[1]);
}
if(t<=2)
w=G.scc[w];
if(swapped)
x^=3;
if(x==2) {
int total;
if(t==1) {
total=ut[w];
} else if(t==2) {
total=in[w];
} else if(t==3) {
total=out[w];
} else {
total=oin[w];
}
int nl=total-r,nr=total-l;
l=nl;
r=nr;
}
if(t==1) {
ul[w].fi=max(ul[w].fi,l);
ul[w].se=min(ul[w].se,r);
} else if(t==2) {
il[w].fi=max(il[w].fi,l);
il[w].se=min(il[w].se,r);
} else if(t==3) {
oul[w].fi=max(oul[w].fi,l);
oul[w].se=min(oul[w].se,r);
} else {
oil[w].fi=max(oil[w].fi,l);
oil[w].se=min(oil[w].se,r);
}
if(w==1&&t==1)
trace(ul[1],l,r);
}
fr(i,1,G.cnt)
if(ul[i].fi>ul[i].se||il[i].fi>il[i].se) {
no=1;
}
fr(i,1,n)
if(oul[i].fi>oul[i].se||oil[i].fi>oil[i].se)
no=1;
if(no) {
cout<<-1<<endl;
return;
}
fr(i,1,G.cnt) {
F.AddEdge(src, 2*n+i, ul[i].fi, ul[i].se);
F.AddEdge(2*n+G.cnt+i, sink, il[i].fi, il[i].se);
}
fr(i,1,n) {
F.AddEdge(2*n+G.scc[i], i, oul[i].fi, oul[i].se);
F.AddEdge(n+i, 2*n+G.cnt+G.scc[i], oil[i].fi, oil[i].se);
}
for(auto i:edg)
F.AddEdge(i.fi, n+i.se, 0, 1);
int ans=F.GetMaxFlow();
if(~ans)
ans=m*c2+(c1-c2)*ans;
cout<<ans<<endl;
}
signed main() {
ios_base::sync_with_stdio(0),cin.tie(0);
srand(chrono::high_resolution_clock::now().time_since_epoch().count());
cout<<fixed<<setprecision(8);
int t=readIntLn(1,100);
fr(i,1,t)
solve();
assert(getchar()==EOF);
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CiNpbmNsdWRlIDxleHQvcGJfZHMvYXNzb2NfY29udGFpbmVyLmhwcD4KI2luY2x1ZGUgPGV4dC9wYl9kcy90cmVlX3BvbGljeS5ocHA+CiNpbmNsdWRlIDxleHQvcm9wZT4KdXNpbmcgbmFtZXNwYWNlIF9fZ251X3BiZHM7CnVzaW5nIG5hbWVzcGFjZSBfX2dudV9jeHg7CiNpZm5kZWYgcmQKI2RlZmluZSB0cmFjZSguLi4pCiNkZWZpbmUgZW5kbCAnXG4nCiNlbmRpZgojZGVmaW5lIHBiIHB1c2hfYmFjawojZGVmaW5lIGZpIGZpcnN0CiNkZWZpbmUgc2Ugc2Vjb25kCiNkZWZpbmUgaW50IGxvbmcgbG9uZwp0eXBlZGVmIGxvbmcgbG9uZyBsbDsKdHlwZWRlZiBsb25nIGRvdWJsZSBmODA7CiNkZWZpbmUgZG91YmxlIGxvbmcgZG91YmxlCiNkZWZpbmUgcGlpIHBhaXI8aW50LGludD4KI2RlZmluZSBwbGwgcGFpcjxsbCxsbD4KI2RlZmluZSBzeih4KSAoKGxvbmcgbG9uZyl4LnNpemUoKSkKI2RlZmluZSBmcihhLGIsYykgZm9yKGludCBhPWI7IGE8PWM7IGErKykKI2RlZmluZSByZXAoYSxiLGMpIGZvcihpbnQgYT1iOyBhPGM7IGErKykKI2RlZmluZSB0cmF2KGEseCkgZm9yKGF1dG8gJmE6eCkKI2RlZmluZSBhbGwoY29uKSBjb24uYmVnaW4oKSxjb24uZW5kKCkKY29uc3QgbGwgaW5mbD0weDNmM2YzZjNmM2YzZjNmM2ZMTDsKY29uc3QgaW50IGluZmk9MHgzZjNmM2YzZjsKLy9jb25zdCBpbnQgbW9kPTk5ODI0NDM1MzsKY29uc3QgaW50IG1vZD0xMDAwMDAwMDA3Owp0eXBlZGVmIHZlY3RvcjxpbnQ+IHZpOwp0eXBlZGVmIHZlY3RvcjxsbD4gdmw7CiAKdHlwZWRlZiB0cmVlPHBpaSwgbnVsbF90eXBlLCBsZXNzPHBpaT4sIHJiX3RyZWVfdGFnLCB0cmVlX29yZGVyX3N0YXRpc3RpY3Nfbm9kZV91cGRhdGU+IG9zZXQ7CmF1dG8gY2xrPWNsb2NrKCk7Cm10MTk5MzdfNjQgcmFuZyhjaHJvbm86OmhpZ2hfcmVzb2x1dGlvbl9jbG9jazo6bm93KCkudGltZV9zaW5jZV9lcG9jaCgpLmNvdW50KCkpOwppbnQgcm5nKGludCBsaW0pIHsKCXVuaWZvcm1faW50X2Rpc3RyaWJ1dGlvbjxpbnQ+IHVpZCgwLGxpbS0xKTsKCXJldHVybiB1aWQocmFuZyk7Cn0KaW50IHBvd20oaW50IGEsIGludCBiKSB7CglpbnQgcmVzPTE7Cgl3aGlsZShiKSB7CgkJaWYoYiYxKQoJCQlyZXM9KHJlcyphKSVtb2Q7CgkJYT0oYSphKSVtb2Q7CgkJYj4+PTE7Cgl9CglyZXR1cm4gcmVzOwp9CiAKbG9uZyBsb25nIHJlYWRJbnQobG9uZyBsb25nIGwsIGxvbmcgbG9uZyByLCBjaGFyIGVuZGQpIHsKCWxvbmcgbG9uZyB4PTA7CglpbnQgY250PTA7CglpbnQgZmk9LTE7Cglib29sIGlzX25lZz1mYWxzZTsKCXdoaWxlKHRydWUpIHsKCQljaGFyIGc9Z2V0Y2hhcigpOwoJCWlmKGc9PSctJykgewoJCQlhc3NlcnQoZmk9PS0xKTsKCQkJaXNfbmVnPXRydWU7CgkJCWNvbnRpbnVlOwoJCX0KCQlpZignMCc8PWcmJmc8PSc5JykgewoJCQl4Kj0xMDsKCQkJeCs9Zy0nMCc7CgkJCWlmKGNudD09MCkgewoJCQkJZmk9Zy0nMCc7CgkJCX0KCQkJY250Kys7CgkJCWFzc2VydChmaSE9MCB8fCBjbnQ9PTEpOwoJCQlhc3NlcnQoZmkhPTAgfHwgaXNfbmVnPT1mYWxzZSk7CiAKCQkJYXNzZXJ0KCEoY250PjE5IHx8ICggY250PT0xOSAmJiBmaT4xKSApKTsKCQl9IGVsc2UgaWYoZz09ZW5kZCkgewoJCQlpZihpc19uZWcpIHsKCQkJCXg9LXg7CgkJCX0KCQkJYXNzZXJ0KGw8PXgmJng8PXIpOwoJCQlyZXR1cm4geDsKCQl9IGVsc2UgewoJCQlhc3NlcnQoZmFsc2UpOwoJCX0KCX0KfQpzdHJpbmcgcmVhZFN0cmluZyhpbnQgbCwgaW50IHIsIGNoYXIgZW5kZCkgewoJc3RyaW5nIHJldD0iIjsKCWludCBjbnQ9MDsKCXdoaWxlKHRydWUpIHsKCQljaGFyIGc9Z2V0Y2hhcigpOwoJCWFzc2VydChnIT0tMSk7CgkJaWYoZz09ZW5kZCkgewoJCQlicmVhazsKCQl9CgkJY250Kys7CgkJcmV0Kz1nOwoJfQoJYXNzZXJ0KGw8PWNudCYmY250PD1yKTsKCXJldHVybiByZXQ7Cn0KbG9uZyBsb25nIHJlYWRJbnRTcChsb25nIGxvbmcgbCwgbG9uZyBsb25nIHIpIHsKCXJldHVybiByZWFkSW50KGwsciwnICcpOwp9CmxvbmcgbG9uZyByZWFkSW50TG4obG9uZyBsb25nIGwsIGxvbmcgbG9uZyByKSB7CglyZXR1cm4gcmVhZEludChsLHIsJ1xuJyk7Cn0Kc3RyaW5nIHJlYWRTdHJpbmdMbihpbnQgbCwgaW50IHIpIHsKCXJldHVybiByZWFkU3RyaW5nKGwsciwnXG4nKTsKfQpzdHJpbmcgcmVhZFN0cmluZ1NwKGludCBsLCBpbnQgcikgewoJcmV0dXJuIHJlYWRTdHJpbmcobCxyLCcgJyk7Cn0KIAppbnQgc3VtX249MCxzdW1fbT0wLHN1bV9xPTA7CiNkZWZpbmUgcnN6KHgsIG4pIHgucmVzaXplKG4pCiNkZWZpbmUgY2xyKHgpIHguY2xlYXIoKQpjbGFzcyBTQ0MgewpwdWJsaWM6CglpbnQgbixjbnQ7IC8vIGNudCAtPiBudW1iZXIgb2Ygc2NjJ3MgZm9ybWVkCgl2ZWN0b3I8dmVjdG9yPGludD4+IGcscmcsc2csY29tcDsgLy8gc2cgLT4gZGFnIHdpdGggYWxsIG5vZGVzIGNvbXByZXNzZWQuCgl2ZWN0b3I8aW50PiBzY2Msb3JkZXI7Cgl2ZWN0b3I8Ym9vbD4gdmlzOwoJdm9pZCByZXNldCgpIHsKCQljbHIoZyksY2xyKHJnKSxjbHIoc2cpLGNscihjb21wKSxjbHIoc2NjKSxjbHIob3JkZXIpLGNscih2aXMpOwoJfQoJdm9pZCBpbml0KGludCBfbikgewoJCXJlc2V0KCk7CgkJbj1fbixjbnQ9MDsKCQlfbis9MjsKCQlyc3ooZywgX24pLHJzeihyZyxfbikscnN6KHNnLF9uKSxyc3ooY29tcCxfbik7CgkJc2NjLnJlc2l6ZShfbiwwKTsKCQl2aXMucmVzaXplKF9uLDApOwoJfQoJdm9pZCBhZGQoaW50IHUsIGludCB2KSB7CgkJZ1t1XS5wdXNoX2JhY2sodik7CgkJcmdbdl0ucHVzaF9iYWNrKHUpOwoJfQoJdm9pZCBjb21wdXRlKCkgewoJCWZyKGksIDEsIG4pCgkJCWlmKCF2aXNbaV0pCgkJCQlkZnMxKGkpOwoJCWZpbGwoYWxsKHZpcyksMCk7CgkJZm9yKGludCBpPW4tMTsgaT49MDsgaS0tKQoJCQlpZighdmlzW29yZGVyW2ldXSkKCQkJCWRmczIob3JkZXJbaV0sKytjbnQpOwoJfQoJdm9pZCBkZnMxKGludCB1KSB7CgkJdmlzW3VdPTE7CgkJZm9yKGludCB2IDogZ1t1XSkKCQkJaWYoIXZpc1t2XSkKCQkJCWRmczEodik7CgkJb3JkZXIucGIodSk7Cgl9Cgl2b2lkIGRmczIoaW50IHUsIGludCBjKSB7CgkJdmlzW3VdPTE7CgkJc2NjW3VdPWM7CgkJY29tcFtjXS5wYih1KTsKCQlmb3IoaW50IHYgOiByZ1t1XSkgewoJCQlpZighdmlzW3ZdKQoJCQkJZGZzMih2LGMpOwoJCQlpZih2aXNbdl0mJmMhPXNjY1t2XSkKCQkJCXNnW3NjY1t2XV0ucGIoYyk7CgkJfQoJfQp9OwogCnN0cnVjdCBFZGdlIHsKCWludCBmcm9tLHRvLGNhcCxmbG93LGluZGV4OwoJRWRnZShpbnQgZnJvbSwgaW50IHRvLCBpbnQgY2FwLCBpbnQgZmxvdywgaW50IGluZGV4KSA6CgkJCWZyb20oZnJvbSksIHRvKHRvKSwgY2FwKGNhcCksIGZsb3coZmxvdyksIGluZGV4KGluZGV4KSB7Cgl9Cn07CnN0cnVjdCBQdXNoUmVsYWJlbCB7CglpbnQgTjsKCXZlY3Rvcjx2ZWN0b3I8RWRnZT4gPiBHOwoJdmVjdG9yPGxsPiBleGNlc3M7Cgl2ZWN0b3I8aW50PiBkaXN0LGFjdGl2ZSxjb3VudDsKCXF1ZXVlPGludD4gUTsKCVB1c2hSZWxhYmVsKGludCBOKSA6CgkJCU4oTiksIEcoTiksIGV4Y2VzcyhOKSwgZGlzdChOKSwgYWN0aXZlKE4pLCBjb3VudCgyKk4pIHsKCX0KCXZvaWQgQWRkRWRnZShpbnQgZnJvbSwgaW50IHRvLCBpbnQgY2FwKSB7CgkJR1tmcm9tXS5wdXNoX2JhY2soRWRnZShmcm9tLHRvLGNhcCwwLEdbdG9dLnNpemUoKSkpOwoJCWlmKGZyb209PXRvKQoJCQlHW2Zyb21dLmJhY2soKS5pbmRleCsrOwoJCUdbdG9dLnB1c2hfYmFjayhFZGdlKHRvLGZyb20sMCwwLEdbZnJvbV0uc2l6ZSgpLTEpKTsgLy8gZm9yIGJpZGlyZWN0aW9uYWwgc2V0IGNhcC4KCX0KCXZvaWQgRW5xdWV1ZShpbnQgdikgewoJCWlmKCFhY3RpdmVbdl0mJmV4Y2Vzc1t2XT4wKSB7CgkJCWFjdGl2ZVt2XT10cnVlOwoJCQlRLnB1c2godik7CgkJfQoJfQoJdm9pZCBQdXNoKEVkZ2UgJmUpIHsKCQlpbnQgYW10PW1pbihleGNlc3NbZS5mcm9tXSxsbChlLmNhcC1lLmZsb3cpKTsKCQlpZihkaXN0W2UuZnJvbV08PWRpc3RbZS50b118fGFtdD09MCkKCQkJcmV0dXJuOwoJCWUuZmxvdys9YW10OwoJCUdbZS50b11bZS5pbmRleF0uZmxvdy09YW10OwoJCWV4Y2Vzc1tlLnRvXSs9YW10OwoJCWV4Y2Vzc1tlLmZyb21dLT1hbXQ7CgkJRW5xdWV1ZShlLnRvKTsKCX0KCXZvaWQgR2FwKGludCBrKSB7CgkJZnIodiwgMCwgTiAtIDEpIHsKCQkJaWYoZGlzdFt2XTxrKQoJCQkJY29udGludWU7CgkJCWNvdW50W2Rpc3Rbdl1dLS07CgkJCWRpc3Rbdl09bWF4KGRpc3Rbdl0sTisxKTsKCQkJY291bnRbZGlzdFt2XV0rKzsKCQkJRW5xdWV1ZSh2KTsKCQl9Cgl9Cgl2b2lkIFJlbGFiZWwoaW50IHYpIHsKCQljb3VudFtkaXN0W3ZdXS0tOwoJCWRpc3Rbdl09MipOOwoJCWZyKGksIDAsIEdbdl0uc2l6ZSgpIC0gMSkKCQkJaWYoR1t2XVtpXS5jYXAtR1t2XVtpXS5mbG93PjApCgkJCQlkaXN0W3ZdPW1pbihkaXN0W3ZdLGRpc3RbR1t2XVtpXS50b10rMSk7CgkJY291bnRbZGlzdFt2XV0rKzsKCQlFbnF1ZXVlKHYpOwoJfQoJdm9pZCBEaXNjaGFyZ2UoaW50IHYpIHsKCQlmb3IoaW50IGk9MDsgZXhjZXNzW3ZdPjAmJmk8R1t2XS5zaXplKCk7IGkrKykKCQkJUHVzaChHW3ZdW2ldKTsKCQlpZihleGNlc3Nbdl0+MCkgewoJCQlpZihjb3VudFtkaXN0W3ZdXT09MSkgewoJCQkJR2FwKGRpc3Rbdl0pOwoJCQl9CgkJCWVsc2UKCQkJCVJlbGFiZWwodik7CgkJfQoJfQoJbGwgR2V0TWF4RmxvdyhpbnQgcywgaW50IHQpIHsKCQljb3VudFswXT1OLTE7CgkJY291bnRbTl09MTsKCQlkaXN0W3NdPU47CgkJYWN0aXZlW3NdPWFjdGl2ZVt0XT0xOwoJCWZyKGksIDAsIChpbnQpR1tzXS5zaXplKCkgLSAxKSB7CgkJCWV4Y2Vzc1tzXSs9R1tzXVtpXS5jYXA7CgkJCVB1c2goR1tzXVtpXSk7CgkJfQoJCXdoaWxlKCFRLmVtcHR5KCkpIHsKCQkJaW50IHY9US5mcm9udCgpOwoJCQlRLnBvcCgpOwoJCQlhY3RpdmVbdl09MDsKCQkJRGlzY2hhcmdlKHYpOwoJCX0KCQlsbCB0b3RmbG93PTA7CgkJZnIoaSwgMCwgKGludClHW3NdLnNpemUoKSAtIDEpCgkJCXRvdGZsb3crPUdbc11baV0uZmxvdzsKCQlyZXR1cm4gdG90ZmxvdzsKCX0KfTsKY29uc3QgaW50IElORj1pbmZpOwpzdHJ1Y3QgTWF4Rmxvd0xvd2VyQm91bmQgewoJUHVzaFJlbGFiZWwgUFI7CglpbnQgTixzLHQsczEsdDE7CglsbCB0b3RhbF9kZW1hbmRzOwoJTWF4Rmxvd0xvd2VyQm91bmQoaW50IE4sIGludCBzLCBpbnQgdCkgOgoJCQlOKE4pLCBQUihOKzIpLCBzKHMpLCB0KHQpLCBzMShOKSwgdDEoTisxKSwgdG90YWxfZGVtYW5kcygwKSB7CgkJUFIuQWRkRWRnZSh0LHMsSU5GKTsKCX0KCXZvaWQgQWRkRWRnZShpbnQgZnJvbSwgaW50IHRvLCBsbCBsbywgbGwgaGkpIHsKCQlQUi5BZGRFZGdlKHMxLHRvLGxvKTsKCQlQUi5BZGRFZGdlKGZyb20sdDEsbG8pOwoJCVBSLkFkZEVkZ2UoZnJvbSx0byxoaS1sbyk7CgkJdG90YWxfZGVtYW5kcys9bG87Cgl9CglsbCBHZXRNYXhGbG93KCkgewoJCWlmKFBSLkdldE1heEZsb3coczEsdDEpPHRvdGFsX2RlbWFuZHMpCgkJCXJldHVybiAtMTsKCQlQdXNoUmVsYWJlbCBQUjEoTik7CgkJbGwgaW5pdGlhbD0wOwoJCWZvcihpbnQgaT0wOyBpPE47IGkrKykgewoJCQlmb3IoYXV0byBlIDogUFIuR1tpXSkgewoJCQkJaWYoZS5mbG93PDB8fGUuY2FwPT0wKQoJCQkJCWNvbnRpbnVlOwoJCQkJaWYoZS50bz49TikKCQkJCQljb250aW51ZTsKCQkJCWlmKGk9PXQmJmUudG89PXMpIHsKCQkJCQlpbml0aWFsPWUuZmxvdzsKCQkJCQljb250aW51ZTsKCQkJCX0KCQkJCVBSMS5BZGRFZGdlKGksZS50byxlLmNhcC1lLmZsb3cpOwoJCQkJUFIxLkFkZEVkZ2UoZS50byxpLGUuZmxvdyk7CgkJCX0KCQl9CgkJcmV0dXJuIGluaXRpYWwrUFIxLkdldE1heEZsb3cocyx0KTsKCX0KfTsKIApjb25zdCBpbnQgTj0zMDAwNTsKaW50IGluW05dLHV0W05dLG9pbltOXSxvdXRbTl07CnBpaSBpbFtOXSx1bFtOXTsKcGlpIG9pbFtOXSxvdWxbTl07CnZvaWQgc29sdmUoKSB7CglpbnQgbj1yZWFkSW50U3AoMSwzMDAwMCksbT1yZWFkSW50U3AoMCwzMDAwMCkscT1yZWFkSW50TG4oMCwzMDAwMDApOwovLwlpbnQgbixtLHE7Ci8vCWNpbj4+bj4+bT4+cTsKCWZyKGksMSxuKSB7CgkJb2lsW2ldPXswLG19OwoJCW91bFtpXT17MCxtfTsKCQlpbFtpXT17MCxtfTsKCQl1bFtpXT17MCxtfTsKCQlpbltpXT11dFtpXT1vaW5baV09b3V0W2ldPTA7Cgl9CglzdW1fbis9bjsKCXN1bV9tKz1tOwoJc3VtX3ErPXE7Cglhc3NlcnQoc3VtX248PTYwMDAwJiZzdW1fbTw9NjAwMDAmJnN1bV9xPD02MDAwMDApOwoJU0NDIEc7CglHLmluaXQobik7Cgl2ZWN0b3I8cGlpPiBlZGc7CglmcihpLDEsbSkgewoJCWludCB1PXJlYWRJbnRTcCgxLG4pLHY9cmVhZEludExuKDEsbik7Ci8vCQlpbnQgdSx2OwovLwkJY2luPj51Pj52OwoJCWFzc2VydCh1IT12KTsKCQlHLmFkZCh1LHYpOwoJCWVkZy5wYih7dSx2fSk7Cgl9CglHLmNvbXB1dGUoKTsKCWZvcihhdXRvIGU6ZWRnKSB7CgkJb3V0W2UuZmldKys7CgkJb2luW2Uuc2VdKys7CgkJdXRbRy5zY2NbZS5maV1dKys7CgkJaW5bRy5zY2NbZS5zZV1dKys7Cgl9CglmcihpLDEsbikgewoJCW9pbFtpXS5zZT1vaW5baV07CgkJb3VsW2ldLnNlPW91dFtpXTsKCQlpbFtpXS5zZT1pbltpXTsKCQl1bFtpXS5zZT11dFtpXTsKCX0KCWludCBjMT1yZWFkSW50U3AoMSwxMDAwMDAwMDAwKSxjMj1yZWFkSW50TG4oMSwxMDAwMDAwMDAwKTsKCWJvb2wgc3dhcHBlZD0wOwoJaWYoYzE+YzIpIHsKCQlzd2FwcGVkPTE7CgkJc3dhcChjMSxjMik7Cgl9CglpbnQgc3JjPTIqbisyKkcuY250KzEsc2luaz0yKm4rMipHLmNudCsyOwoJTWF4Rmxvd0xvd2VyQm91bmQgRigyKm4rMipHLmNudCs1LHNyYyxzaW5rKTsKCWJvb2wgbm89MDsKCWZyKGksMSxxKSB7CgkJaW50IHQ9cmVhZEludFNwKDEsNCksdz1yZWFkSW50U3AoMSxuKSx4PXJlYWRJbnRTcCgxLDIpLGw9cmVhZEludFNwKDAsbSkscj1yZWFkSW50TG4obCxtKTsKCQlpZihHLnNjY1t3XT09MSYmdDw9MikgewoJCQl0cmFjZSh0LHcseCxsLHIsdWxbMV0pOwoJCX0KCQlpZih0PD0yKQoJCQl3PUcuc2NjW3ddOwoJCWlmKHN3YXBwZWQpCgkJCXhePTM7CgkJaWYoeD09MikgewoJCQlpbnQgdG90YWw7CgkJCWlmKHQ9PTEpIHsKCQkJCXRvdGFsPXV0W3ddOwoJCQl9IGVsc2UgaWYodD09MikgewoJCQkJdG90YWw9aW5bd107CgkJCX0gZWxzZSBpZih0PT0zKSB7CgkJCQl0b3RhbD1vdXRbd107CgkJCX0gZWxzZSB7CgkJCQl0b3RhbD1vaW5bd107CgkJCX0KCQkJaW50IG5sPXRvdGFsLXIsbnI9dG90YWwtbDsKCQkJbD1ubDsKCQkJcj1ucjsKCQl9CgkJaWYodD09MSkgewoJCQl1bFt3XS5maT1tYXgodWxbd10uZmksbCk7CgkJCXVsW3ddLnNlPW1pbih1bFt3XS5zZSxyKTsKCQl9IGVsc2UgaWYodD09MikgewoJCQlpbFt3XS5maT1tYXgoaWxbd10uZmksbCk7CgkJCWlsW3ddLnNlPW1pbihpbFt3XS5zZSxyKTsKCQl9IGVsc2UgaWYodD09MykgewoJCQlvdWxbd10uZmk9bWF4KG91bFt3XS5maSxsKTsKCQkJb3VsW3ddLnNlPW1pbihvdWxbd10uc2Uscik7CgkJfSBlbHNlIHsKCQkJb2lsW3ddLmZpPW1heChvaWxbd10uZmksbCk7CgkJCW9pbFt3XS5zZT1taW4ob2lsW3ddLnNlLHIpOwoJCX0KCQlpZih3PT0xJiZ0PT0xKQoJCQl0cmFjZSh1bFsxXSxsLHIpOwoJfQoJZnIoaSwxLEcuY250KQoJCWlmKHVsW2ldLmZpPnVsW2ldLnNlfHxpbFtpXS5maT5pbFtpXS5zZSkgewoJCQlubz0xOwoJCX0KCWZyKGksMSxuKQoJCWlmKG91bFtpXS5maT5vdWxbaV0uc2V8fG9pbFtpXS5maT5vaWxbaV0uc2UpCgkJCW5vPTE7CglpZihubykgewoJCWNvdXQ8PC0xPDxlbmRsOwoJCXJldHVybjsKCX0KCWZyKGksMSxHLmNudCkgewoJCUYuQWRkRWRnZShzcmMsIDIqbitpLCB1bFtpXS5maSwgdWxbaV0uc2UpOwoJCUYuQWRkRWRnZSgyKm4rRy5jbnQraSwgc2luaywgaWxbaV0uZmksIGlsW2ldLnNlKTsKCX0KCWZyKGksMSxuKSB7CgkJRi5BZGRFZGdlKDIqbitHLnNjY1tpXSwgaSwgb3VsW2ldLmZpLCBvdWxbaV0uc2UpOwoJCUYuQWRkRWRnZShuK2ksIDIqbitHLmNudCtHLnNjY1tpXSwgb2lsW2ldLmZpLCBvaWxbaV0uc2UpOwoJfQoJZm9yKGF1dG8gaTplZGcpCgkJRi5BZGRFZGdlKGkuZmksIG4raS5zZSwgMCwgMSk7CglpbnQgYW5zPUYuR2V0TWF4RmxvdygpOwoJaWYofmFucykKCQlhbnM9bSpjMisoYzEtYzIpKmFuczsKCWNvdXQ8PGFuczw8ZW5kbDsKfQogCnNpZ25lZCBtYWluKCkgewoJaW9zX2Jhc2U6OnN5bmNfd2l0aF9zdGRpbygwKSxjaW4udGllKDApOwoJc3JhbmQoY2hyb25vOjpoaWdoX3Jlc29sdXRpb25fY2xvY2s6Om5vdygpLnRpbWVfc2luY2VfZXBvY2goKS5jb3VudCgpKTsKCWNvdXQ8PGZpeGVkPDxzZXRwcmVjaXNpb24oOCk7CglpbnQgdD1yZWFkSW50TG4oMSwxMDApOwoJZnIoaSwxLHQpCgkJc29sdmUoKTsKCWFzc2VydChnZXRjaGFyKCk9PUVPRik7CglyZXR1cm4gMDsKfQog