#include "Aoi.h"
#include <bits/stdc++.h>
using namespace std;
namespace
{
typedef long long ll;
const ll INF = 1e18;
int n;
vector<int> A, B;
vector<ll> C;
vector<int> con[10005];
ll dist[10005];
int prec[10005];
void calc_dist()
{
for(int i=0;i<n;i++)
{
dist[i] = INF;
prec[i] = -1;
}
priority_queue<pair<ll,int>> pq;
dist[0] = 0;
pq.push({0, 0});
while(!pq.empty())
{
int nod = pq.top().second;
ll cdist = -pq.top().first;
pq.pop();
if(cdist != dist[nod])
continue;
for(auto eid:con[nod])
{
int adj = A[eid] + B[eid] - nod;
ll w = C[eid];
if(dist[adj] > dist[nod] + w)
{
dist[adj] = dist[nod] + w;
prec[adj] = eid;
pq.push({-dist[adj], adj});
}
}
}
}
}
std::string aoi(int N, int M, int Q, int K, std::vector<int> copA,
std::vector<int> copB, std::vector<ll> copC,
std::vector<int> T, std::vector<int> X)
{
mt19937 rnd(139881);
const int CT = 1000;
assert(n == 0);
n = N;
A = copA;
B = copB;
C = copC;
for(int i=0;i<M;i++)
{
con[A[i]].push_back(i);
con[B[i]].push_back(i);
}
calc_dist();
vector<ll> init_dist(Q);
for(int i=0;i<Q;i++)
init_dist[i] = dist[T[i]];
vector<int> good_masks;
for(int i=0;i<Q;i++)
good_masks.push_back(1<<i);
vector<int> ord;
for(int mask=1;mask<(1<<Q);mask++)
if(__builtin_popcount(mask) > 1)
ord.push_back(mask);
shuffle(ord.begin(), ord.end(), rnd);
vector<bool> used(M);
for(int pas=0;pas<min(CT, (int)ord.size());pas++)
{
int mask = ord[pas];
for(int i=0;i<M;i++)
used[i] = 0;
C = copC;
calc_dist();
for(int i=0;i<Q;i++)
{
if((1<<i)&mask)
{
int cur = T[i];
while(cur != 0)
{
int eid = prec[cur];
used[eid] = 1;
cur = A[eid] + B[eid] - cur;
}
}
}
for(int i=0;i<K;i++)
{
if(used[X[i]])
C[X[i]] = 1;
else
C[X[i]] = INF;
}
calc_dist();
bool bun = 1;
for(int i=0;i<Q;i++)
{
ll sum = 0;
int cur = T[i];
while(cur != 0)
{
int eid = prec[cur];
sum = sum + copC[eid];
cur = A[eid] + B[eid] - cur;
}
if(sum != init_dist[i])
{
bun = 0;
break;
}
}
if(bun)
good_masks.push_back(mask);
}
vector<bool> isgood((1<<Q), 0);
for(int x:good_masks)
isgood[x] = 1;
vector<int> dp((1<<Q), Q + 5);
vector<int> ult((1<<Q), -1);
dp[0] = 0;
for(int mask=1;mask<(1<<Q);mask++)
{
vector<int> submasks;
int cur = mask;
while(cur != 0)
{
cur = (cur - 1) & mask;
submasks.push_back(cur);
}
for(int subm:submasks)
{
assert((mask | subm) == mask);
if(isgood[mask - subm] && dp[mask] > dp[subm] + 1)
{
dp[mask] = dp[subm] + 1;
ult[mask] = mask - subm;
}
}
}
assert(dp[(1<<Q) - 1] != Q + 5);
string sol;
int mask = (1<<Q) - 1;
while(mask > 0)
{
int now = ult[mask];
mask -= now;
vector<bool> used(M,0);
for(int i=0;i<Q;i++)
{
if((1<<i)&now)
{
int cur = T[i];
while(cur != 0)
{
int eid = prec[cur];
used[eid] = 1;
cur = A[eid] + B[eid] - cur;
}
}
}
for(int i=0;i<Q;i++)
{
if((1<<i)&now)
sol.push_back('1');
else
sol.push_back('0');
}
for(int i=0;i<K;i++)
{
if(used[X[i]])
sol.push_back('1');
else
sol.push_back('0');
}
}
return sol;
}
#include "Bitaro.h"
#include <bits/stdc++.h>
using namespace std;
namespace
{
typedef long long ll;
const ll INF = 1e18;
int n;
vector<int> A, B;
vector<ll> C;
vector<int> con[10005];
ll dist[10005];
int prec[10005];
void calc_dist()
{
for(int i=0;i<n;i++)
{
dist[i] = INF;
prec[i] = -1;
}
priority_queue<pair<ll,int>> pq;
dist[0] = 0;
pq.push({0, 0});
while(!pq.empty())
{
int nod = pq.top().second;
ll cdist = -pq.top().first;
pq.pop();
if(cdist != dist[nod])
continue;
for(auto eid:con[nod])
{
int adj = A[eid] + B[eid] - nod;
ll w = C[eid];
if(dist[adj] > dist[nod] + w)
{
dist[adj] = dist[nod] + w;
prec[adj] = eid;
pq.push({-dist[adj], adj});
}
}
}
}
}
void bitaro(int N, int M, int Q, int K, std::vector<int> copA, std::vector<int> copB,
std::vector<long long> copC, std::vector<int> T, std::vector<int> X,
std::string s)
{
n = N;
A = copA;
B = copB;
C = copC;
for(int i=0;i<M;i++)
{
con[A[i]].push_back(i);
con[B[i]].push_back(i);
}
vector<vector<int>> ans(Q);
assert((int)s.size() % (Q+K) == 0);
for(int le=0;le<s.size();le+=Q+K)
{
for(int i=0;i<K;i++)
{
if(s[le + Q + i] == '1')
{
C[X[i]] = 1;
}
else
{
C[X[i]] = INF;
}
}
calc_dist();
for(int i=0;i<Q;i++)
{
if(s[le + i] == '1')
{
int cur = T[i];
while(cur != 0)
{
int eid = prec[cur];
ans[i].push_back(eid);
cur = A[eid] + B[eid] - cur;
}
reverse(ans[i].begin(), ans[i].end());
}
}
}
for(int i=0;i<Q;i++)
answer(ans[i]);
}
/*
3 3
1 2 1
0 2 2
0 1 3
2
2 1
2
0 1
*/