
GRE Words Once More!
Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 205 Accepted Submission(s): 32
Thanks to modern techniques, Matt uses automata instead of old-fasioned vocabulary books.
The automata used by Matt is a directed acyclic graph (DAG) with N vertices and M edges. The vertices are conveniently numbered by 1, 2, . . . , N . Each edge is labeled with an integer. Additionally, some vertices are marked as special.
A GRE word is obtained by concatenating the labels on the path from vertex 1 to a special vertex.
Now, Matt has Q questions. The i-th question is asking for the length of ki-th smallest words among all the GRE words he can obtain in lexicographical order.
For each test case, the first line contains three integers N, M, Q (2 ≤ N ≤ 105, 0 ≤ M ≤ 105, 1 ≤ Q ≤ 105).
The second line contains N - 1 integers s2, . . . , sn. If the i-th vertex is special, then si = 1. Otherwise, si = 0. Vertex 1 is never special.
Each of the following M lines contains three integers ai, bi, ci denoting an edge from vertex ai to vertex bi labeled with ci (1 ≤ ai, bi ≤ N, 1 ≤ ci ≤ 109). For each vertex v, all outgoing edges are labeled with distinct integers.
Each of the following Q lines contains the integer ki (1 ≤ ki ≤ 108) of the i-th question.
Then, for each question, output the length of the word in one line. If the word does not exist, output “-1” (without quotes) instead.
3 3 4
1 1
1 2 1
1 3 12
2 3 3
1
2
3
4
1
2
1
-1
There are 3 GRE words in total (sorted in lexicographical order):
1. (1)
2. (1, 3)
3. (12)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
const int N=,M=;
vector<pair<int,int> >g[N];
int ans[M+],f[N],be[N],ed[N],tot;
int st[N],dep[N],vis[N],mem[N],top;
int T,cas=,q,n,m,Q;
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&Q);tot=;
for(int i=;i<=n;i++)scanf("%d",&f[i]);
for(int i=,a,b,v;i<=m;i++){
scanf("%d%d%d",&a,&b,&v);
g[a].push_back(make_pair(v,b));
}
for(int i=;i<=n;i++)
sort(g[i].begin(),g[i].end());
st[top=]=;dep[top]=;
memset(vis,,sizeof(vis));
memset(be,,sizeof(be));
memset(ed,,sizeof(ed));
while(top){
int x=st[top],d=dep[top];
if(vis[top]){
if(!ed[x])ed[x]=tot;
vis[top]=;top-=;
continue;
}
vis[top]=;
if(be[x]){
int depth=-mem[x]+d;
for(int i=be[x];i<=ed[x];i++){
ans[++tot]=ans[i]+depth;
if(tot>=M)break;
}if(tot>=M)break;
continue;
}
be[x]=tot+;mem[x]=d;
if(f[x])ans[++tot]=d;
if(tot>=M)break;
for(int i=g[x].size()-;~i;i--){
st[++top]=g[x][i].second;
dep[top]=d+;
}
}
printf("Case #%d:\n",++cas);
while(Q--){
scanf("%d",&q);
if(q>tot)printf("-1\n");
else printf("%d\n",ans[q]);
}
for(int i=;i<=n;i++)g[i].clear();
}
return ;
}