• [CF864F]Cities Excursions


    题目大意:
      一个$n(nle3000)$个点的有向图,$q(qle4 imes10^5)$组询问,每次询问$s_i,t_i$之间是否存在一条字典序最小的路径(可以重复经过不为$t_i$的结点)。若存在,求出该路径上经过的第$k_i$个结点。

    思路:
      将原图的边反向。考虑根据$t_i$对所有询问进行分组。对于$t_i$相同的询问,在反向图中DFS,求出每个结点到$t_i$的最小字典序路径中的下一个结点是多少,这可以转化为一个树形结构。若$s_i$与$t_i$不连通,则说明路径不存在;若$s_i$的第$2^{lfloorlog_2n floor+1}$级祖先存在,则说明存在环。询问第$k_i$个结点可以树上倍增。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<cstring>
     4 #include<forward_list>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 constexpr int N=3001,Q=4e5,logN=13;
    13 std::forward_list<int> e[N];
    14 struct Query {
    15     int s,k,id;
    16 };
    17 std::forward_list<Query> q[N];
    18 int ans[Q],anc[N][logN];
    19 inline int lg2(const float &x) {
    20     return ((unsigned&)x>>23&255)-127;
    21 }
    22 void dfs(const int &x,const int &par,const int &s) {
    23     anc[x][0]=par;
    24     for(auto &y:e[x]) {
    25         if(y==s||(anc[y][0]&&anc[y][0]<=x)) continue;
    26         dfs(y,x,s);
    27     }
    28 }
    29 int main() {
    30     const int n=getint(),m=getint(),cnt_q=getint(),lim=lg2(n)+1;
    31     for(register int i=0;i<m;i++) {
    32         const int u=getint(),v=getint();
    33         e[v].push_front(u);
    34     }
    35     for(register int i=0;i<cnt_q;i++) {
    36         const int s=getint(),t=getint(),k=getint();
    37         q[t].push_front({s,k-1,i});
    38     }
    39     for(register int i=1;i<=n;i++) {
    40         if(q[i].empty()) continue;
    41         memset(anc,0,sizeof anc);
    42         dfs(i,0,i);
    43         for(register int j=1;j<=lim;j++) {
    44             for(register int i=1;i<=n;i++) {
    45                 anc[i][j]=anc[anc[i][j-1]][j-1];
    46             }
    47         }
    48         for(register auto &j:q[i]) {
    49             if(!anc[j.s][0]||anc[j.s][lim]) continue;
    50             for(register int i=0;j.k;j.k>>=1,i++) {
    51                 if(j.k&1) j.s=anc[j.s][i];
    52             }
    53             ans[j.id]=j.s;
    54         }
    55     }
    56     for(register int i=0;i<cnt_q;i++) {
    57         printf("%d
    ",ans[i]?:-1);
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    GCD之各种派发
    Effective Objective-C 笔记之熟悉OC
    正则表达式之正向预查和负向预查
    vue的实例属性$refs
    vue的实例属性$options
    vue的实例属性$data
    vue的实例属性$el
    vue强制更新$forceUpdate()
    vue的extends的使用
    vue的mixins的使用
  • 原文地址:https://www.cnblogs.com/skylee03/p/9071557.html
Copyright © 2020-2023  润新知