题意:
题意: 给定一个有向图,询问由s到t的字典序最小的路径的第k个点 输入: 第一行三个整数n(2<=n<=3000),m(0<=m<=3000),q(1<=q<=400000) 接下来m行每行两个整数x,y(1<=x,y<=n且x≠y)表示由x到y有一条路(由城市x到y最多只有一条路) 接下来q行每行三个整数s,t(1<=s,t<=n且s≠t),k(1<=k<=3000) 输出: q行,每行对应一个答案 若s与t不连通输出-1 若字典序最小的路径构成环输出-1
感谢@凌幽 提供的翻译(洛谷用户)
解:
1、如果从s贪心的走形成环了,那么之后的点一定不会从s出发达到。
2、询问第k个点,在树上可以用lca的祖先数组倍增来完成询问。
3、可以倒着思考这个问题,考虑所有可以贪心到达,t的节点,---->会构成一课反向树,
整个树上的所有节点都是可以出发到达跟的节点,
4、考虑将所有的询问排序,我们那么第k节点就是第K-1个祖先,。
#include<bits/stdc++.h>
using namespace std;
const int maxn =3e3+10;
const int logm=18;
int n,m,q,ans[412345],anc[maxn][logm],dep[maxn],vis[maxn];
vector<int>vec[maxn],vec_r[maxn];
int rd(){int tt;scanf("%d",&tt);return tt;}
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
bool ok[maxn][maxn];
struct node{int x,k,ind;};
vector<node>que[maxn];
void Dfs(int x){
vis[x]=1;
for(int i=0;i<vec_r[x].size();i++){
int y=vec_r[x][i];
anc[y][0]=x;
dep[y]=dep[x]+1;
for(int j=1;j<logm;j++){
anc[y][j]=anc[anc[y][j-1]][j-1];
}
Dfs(y);
}
}
int ask(int x,int k){
for(int i=logm-1;i>=0;--i){
if((k>>i)&1){
x=anc[x][i];
}
}return x;
}
void work(int x){
if(que[x].size()==0)return ;
mem(dep,0);dep[x]=1;
mem(vis,0);
for(int i=1;i<=n;i++){vec_r[i].clear();}
for(int i=1;i<=n;i++){
if(!ok[i][x] or i==x)continue;
for(int j=0;j<vec[i].size();j++){
int tem=vec[i][j];
if(ok[tem][x])
{
vec_r[tem].pb(i);break;
}
}
}
Dfs(x);
for(int i=0;i<que[x].size();i++){
int xx=que[x][i].x;
if(dep[xx]<que[x][i].k or !vis[xx]){ans[que[x][i].ind]=-1;continue;}
ans[que[x][i].ind]=ask(xx,que[x][i].k-1);
}
}
void dfs(int x,int from){
if(ok[from][x])return ;
ok[from][x]=1;
for(int i=0;i<vec[x].size();i++){
int y=vec[x][i];
dfs(y,from);
}
}
signed main(){
#ifdef swt
freopen("input2.txt","r",stdin);
#endif
#define en '\n'
cin>>n>>m>>q;
for(int i=1;i<=m;i++){int x=rd(),y=rd();vec[x].pb(y);}
for(int i=1;i<=n;i++){sort(vec[i].begin(),vec[i].end());}
for(int i=1;i<=n;i++)dfs(i,i);
for(int i=1;i<=q;i++){
int s=rd(),t=rd(),k=rd();
if(!ok[s][t]){ans[i]=-1;
continue;
}
que[t].pb((node){s,k,i});
}
for(int i=1;i<=n;i++){work(i);}
for(int i=1;i<=q;i++){
cout<<ans[i]<<en;
}
}