真的是很有意思的题。
因为有重复的边,我想了很多贪心搞法都错了。最后还是看了标解。
trie+bfs+dfs+二分+rmq。OMG
最重要的还是几点吧:
1.通过在trie上dfs/bfs可以知道某个节点的hash值大小,因为有mod,直接比较值是没法比较大小的。
2.bfs可以将树上同一深度的点放在一个连续区间,而dfs可以求出子树区间,结合就能找到子树中某个深度的最值。
注意m=0时输出0。
写这种很多东西结合的看起来很长的题,最好先把变量名规划好,要用的东西也在纸上标记好,这样实现起来事半功倍。
很多时候觉得手速不够,现在想来还是没想清楚,思考纠结的时间远大于敲代码的时间。
因为有重复的边,我想了很多贪心搞法都错了。最后还是看了标解。
trie+bfs+dfs+二分+rmq。OMG
最重要的还是几点吧:
1.通过在trie上dfs/bfs可以知道某个节点的hash值大小,因为有mod,直接比较值是没法比较大小的。
2.bfs可以将树上同一深度的点放在一个连续区间,而dfs可以求出子树区间,结合就能找到子树中某个深度的最值。
注意m=0时输出0。
写这种很多东西结合的看起来很长的题,最好先把变量名规划好,要用的东西也在纸上标记好,这样实现起来事半功倍。
很多时候觉得手速不够,现在想来还是没想清楚,思考纠结的时间远大于敲代码的时间。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define NN 101100
#define mpa make_pair
#define pb push_back
const long long mod=1000000007;
const long long inf=1000000100;
const long long mag=26;
typedef pair<int,int> pii;
vector<pii> ed[NN];
int n;
int bseq[NN],bn;
int dn;
int seq[NN],tseq;
int vis[NN];
int depbeg[NN],depend[NN];
int dbeg[NN],dend[NN],dep[NN];
long long sv[NN];
int r[NN];
long long val[NN];
//trie------------------
int tott;
int root;
struct trie{
int son[26];
void init(){memset(son,0,sizeof(son));}
}t[NN];
void dfsbuild(int u,int f,int p,long long tv){//build trie
r[u]=p;
val[u]=tv;
int v,i,id;
int sz=ed[u].size();
for(i=0;i<sz;++i){
v=ed[u][i].second;
if (v==f) continue;
id=ed[u][i].first;
if (t[p].son[id]) dfsbuild(v,u,t[p].son[id],(long long)(tv*mag+(long long)id)%mod);
else {
t[p].son[id]=++tott;
t[tott].init();
dfsbuild(v,u,tott,(long long)(tv*mag+(long long)id)%mod);
}
}
}
void dfstrie(int u){//get seq
seq[u]=++tseq;
int i;
long long tmp;
for(i=25;i>=0;--i){
if (t[u].son[i]){
dfstrie(t[u].son[i]);
}
}
}
//trie--------------------
//rmq-------------------------------------------------------
int mi[NN][18];
int mv[NN][18];
void rmqinit(int n){
int m=-1,k=n;
while(k) {m++;k>>=1;}
int i,j;
for(i=1;i<=n;i++) {mi[i][0]=seq[r[bseq[i]]];mv[i][0]=bseq[i];}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
mi[j][i]=mi[j][i-1];mv[j][i]=mv[j][i-1];
if (j+(1<<(i-1))<=n){
if (mi[j][i]>mi[j+(1<<(i-1))][i-1]){
mi[j][i]=mi[j+(1<<(i-1))][i-1];
mv[j][i]=mv[j+(1<<(i-1))][i-1];
}
}
}
}
}
int rmqmin(int l,int r){
int m=-1,k=r+1-l;
while(k) {k>>=1;m++;}
if (mi[l][m]<mi[r+1-(1<<m)][m]) return mv[l][m];
else return mv[r+1-(1<<m)][m];
}
//--------------------------rmq----------------------------------
void bfs(){
queue<int> q;
memset(vis,0,sizeof(vis));
int u=1,i,v;
q.push(u);
vis[u]=1;
bn=0;
memset(depbeg,-1,sizeof(depbeg));
while(!q.empty()){
u=q.front();q.pop();
bseq[++bn]=u;
depend[vis[u]]=bn;
if (depbeg[vis[u]]==-1) {depbeg[vis[u]]=bn;}
for(i=0;i<ed[u].size();++i){
v=ed[u][i].second;
if (!vis[v]){
q.push(v);
vis[v]=vis[u]+1;
}
}
}
}
void dfs(int u,int f,int ddep){
dep[u]=ddep;
dbeg[u]=++dn;
int i,v;
for(i=0;i<ed[u].size();++i){
v=ed[u][i].second;
if (v==f) continue;
dfs(v,u,ddep+1);
}
dend[u]=++dn;
}
void init_sv(){
int i;
sv[0]=1;
for(i=1;i<=100010;++i){
sv[i]=(sv[i-1]*mag)%mod;
}
}
void init(int n){
int i;
tott=1;
root=1;
t[root].init();
tseq=0;
for(i=0;i<=n+100;++i){
ed[i].clear();
}
memset(depbeg,-1,sizeof(depbeg));
}
int bsch_lower(int ll,int rr,int val){
int m,ans=rr+1;
while(ll<=rr){
m=(ll+rr)/2;
if (dbeg[bseq[m]]>val){
if (ans>m) ans=m;
rr=m-1;
}
else ll=m+1;
}
return ans;
}
int bsch_upper(int ll,int rr,int val){
int m,ans=ll-1;
while(ll<=rr){
m=(ll+rr)/2;
if (dbeg[bseq[m]]<val){
if (ans<m) ans=m;
ll=m+1;
}
else rr=m-1;
}
return ans;
}
long long work(int u,int m){
int tmp=dep[u]+m,v;
if (tmp>n+1||depbeg[tmp]==-1) return inf;
int lb=bsch_lower(depbeg[tmp],depend[tmp],dbeg[u]);
int ub=bsch_upper(depbeg[tmp],depend[tmp],dend[u]);
if (ub>=lb){
v=rmqmin(lb,ub);
return (val[v]-val[u]*sv[dep[v]-dep[u]]%mod+mod)%mod;
}
else return inf;
}
int main(){
//freopen("4601in.txt","r",stdin);
int cas,i,a,b,q,u,m;
char ts[20];
init_sv();
scanf("%d",&cas);
while(cas--){
scanf("%d",&n);
init(n);
for(i=1;i<n;++i){
scanf("%d%d%s",&a,&b,ts);
ed[a].pb(mpa(ts[0]-'a',b));
ed[b].pb(mpa(ts[0]-'a',a));
}
dfsbuild(1,0,root,0);
tseq=0;
dfstrie(1);
bfs();
rmqinit(n);
dn=0;
dfs(1,-1,1);
scanf("%d",&q);
for(i=1;i<=q;++i){
scanf("%d%d",&u,&m);
if (u>n||u<0) {puts("IMPOSSIBLE");continue;}
if (m==0) puts("0");
else {
long long tmp=work(u,m);
if (tmp==inf) puts("IMPOSSIBLE");
else printf("%I64d\n",tmp);
}
}
}
return 0;
}