题意:
给定一个有无环图,边权代表一个字母(事实上用数字表示的),然后给定2~n个点的特殊性,1表示特殊,0表示不特殊,从1出发,到一个特殊点停止,这条路径上的所有字母拼成一个单词,将所有单词按照字典序排序后,然后Q组询问,问第k个单词的长度是多少。
思路:
参考自:http://blog.csdn.net/yuanjunlai141/article/details/73744137
DFS暴力记录1e8个单词的长度(ML:512MB)
剪枝:
由于每个点后对应的单词数量是一定的,当遇到已访问的点时,复制点后的单词后直接return即可。
注意单词的长度的变化即可。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
const int MAXM=1e8+10;
int n,m,q;
int marked[MAXN],dep[MAXN];
int ans[MAXM+1],ppp,loc[MAXN],cnt[MAXN];
typedef struct Node{
int x;
int val;
bool operator < (const Node &a){
return val<a.val;
}
}Node;
vector <Node> son[MAXN];
void dfs(int pos,int depth){
if(ppp<MAXM){
if(!dep[pos]){
dep[pos]=depth;
loc[pos]=ppp;
if(marked[pos]){
ans[++ppp]=depth;
cnt[pos]++;
}
int len=son[pos].size();
for(int i=0;i<len;i++) dfs(son[pos][i].x,depth+1),cnt[pos]+=cnt[son[pos][i].x];
}else{
for(int i=loc[pos]+1;i<=(loc[pos]+cnt[pos])&&ppp<MAXM;i++)
ans[++ppp]=ans[i]-dep[pos]+depth;
}
}
}
int main()
{
int T,x,y,z;
scanf("%d",&T);
for(int Case=1;Case<=T;Case++){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++) son[i].clear();
memset(dep,0,sizeof(dep));
memset(cnt,0,sizeof(cnt));
for(int i=2;i<=n;i++) scanf("%d",&marked[i]);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
son[x].push_back({y,z});
}
for(int i=1;i<=n;i++) sort(son[i].begin(),son[i].end());
ppp=0;dfs(1,0);
printf("Case #%d:\n",Case);
for(int i=0;i<q;i++){
scanf("%d",&x);
printf("%d\n",x<=ppp?ans[x]:-1);
}
}
}