zoukankan      html  css  js  c++  java
  • 【xsy1300】 原题的旅行 最短路+倍增

    题目大意:有一个$n$个点,$m$条边的无向图,玩家走过第$i$条边,血槽中的血会下降$v_i$点,如果不足$v_i$点,这人会当场去世。

    这$n$个点中,有若干个是关键点,在这些关键点可以将血槽补满。

    现在有$q$组询问,每次问一个玩家的血槽至少需要多大,才能从$x$走到$y$。

    保证$x$号点和$y$号点可以把你的血槽补满

    数据范围:$n≤10^5$,$m≤2 imes 10^5$,$V≤10^9$。

    我们考虑如果每个点都能补满血槽的话,我们显然可以对原图求一遍最小生成树,每次我们在这颗树上倍增取最大值即可。

    不过这一题非常烦人,只有一部分点是可以的。

    我们考虑对每个点i处理出$dist[i]$和$from[i]$。

    其中,$from[i]$表示距离$i$号点最近的可以补满$i$号点血槽的点的编号,$dist[i]$表示$i$号点距离$from[i]$的距离。

    对于原图中任意一条边$(u,v,w)$,若满足$from[u]!=from[v]$,那么我们就在新图中加入$(from[u],from[v],dist[u]+dist[v]+w)$

    然后,我们对新图求一个最小生成树,然后在这棵树上倍增即可。

    时间复杂度显然是$O((m+n+q)log n)$的。

     1 #include<bits/stdc++.h>
     2 #define L long long
     3 #define M 200005
     4 #define INF (1LL<<60)
     5 using namespace std;
     6 
     7 struct edge{L u,v,next;}e[M*4]={0}; L head[M]={0},use=0;
     8 void add(L x,L y,L z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
     9 L dist[M]={0},from[M]={0};
    10 L n,m; L ok[M]={0},vis[M]={0};char c[M]={0};
    11 
    12 struct node{
    13     L u,bel; L dis;
    14     node(){u=bel=dis=0;}
    15     node(L U,L Bel,L Dis){u=U; bel=Bel; dis=Dis;}
    16     friend bool operator <(node a,node b){
    17         return a.dis>b.dis;
    18     }
    19 }; priority_queue<node> q;
    20 
    21 void dij(){
    22     memset(dist,1,sizeof(dist));
    23     for(L i=1;i<=n;i++) if(ok[i]) q.push(node(i,i,0));
    24     while(!q.empty()){
    25         node U=q.top(); q.pop();
    26         L u=U.u; if(dist[u]!=dist[0]) continue;
    27         dist[u]=U.dis; 
    28         from[u]=U.bel;
    29         for(L i=head[u];i;i=e[i].next)
    30         if(dist[u]+e[i].v<=dist[e[i].u]){
    31             q.push(node(e[i].u,U.bel,dist[u]+e[i].v));
    32         }
    33     }
    34 }
    35 
    36 struct edge2{
    37     L u,v;L w;
    38     edge2(){u=v=w=0;}
    39     edge2(L U,L V,L W){u=U; v=V; w=W;}
    40     friend bool operator <(edge2 a,edge2 b){return a.w<b.w;}
    41 }p[M*2]; L N=0;
    42 
    43 L fa[M]={0}; L get(L x){return x==fa[x]?x:fa[x]=get(fa[x]);}
    44 
    45 L f[M][20]={0},dep[M]={0}; L mx[M][20]={0};
    46 void dfs(L x,L fa,L F){
    47     f[x][0]=fa; dep[x]=dep[fa]+1; mx[x][0]=F;
    48     for(L i=1;i<20;i++) f[x][i]=f[f[x][i-1]][i-1],mx[x][i]=max(mx[x][i-1],mx[f[x][i-1]][i-1]);
    49     for(L i=head[x];i;i=e[i].next) if(e[i].u!=fa) dfs(e[i].u,x,e[i].v);
    50 }
    51 L getlca(L x,L y){
    52     if(dep[x]<dep[y]) swap(x,y); L cha=dep[x]-dep[y];
    53     for(L i=19;~i;i--) if((1<<i)&cha) x=f[x][i];
    54     for(L i=19;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    55     if(x==y) return x; return f[x][0];
    56 }
    57 L jump(L x,L k){
    58     L maxn=0;
    59     for(L i=19;~i;i--) if((1<<i)&k){
    60         maxn=max(maxn,mx[x][i]);
    61         x=f[x][i];
    62     }
    63     return maxn;
    64 }
    65 
    66 main(){
    67     scanf("%lld%lld",&n,&m);
    68     scanf("%s",c+1); for(L i=1;i<=n;i++) ok[i]=(c[i]=='1');
    69     for(L i=1,x,y,z;i<=m;i++) scanf("%lld%lld%lld",&x,&y,&z),add(x,y,z),add(y,x,z);
    70     dij();
    71     for(L x=1;x<=n;x++)
    72     for(L i=head[x];i;i=e[i].next) if(i&1){
    73         L X=x,Y=e[i].u;
    74         if(from[X]!=from[Y]){
    75             p[++N]=edge2(from[X],from[Y],dist[X]+dist[Y]+e[i].v);
    76         }
    77     }
    78     sort(p+1,p+N+1);
    79     memset(head,0,sizeof(head)); use=0; memset(e,0,sizeof(e));
    80     for(L i=1;i<=n;i++) fa[i]=i;
    81     
    82     for(L i=1;i<=N;i++){
    83         L u=get(p[i].u),v=get(p[i].v);
    84         if(u==v) continue; fa[u]=v;
    85         u=p[i].u; v=p[i].v;
    86         add(u,v,p[i].w); add(v,u,p[i].w);
    87     }
    88     L sta=0; for(L i=1;i<=n;i++) if(ok[i]) {sta=i; break;}
    89     
    90     dfs(sta,0,0);
    91     
    92     L q; scanf("%lld",&q);
    93     while(q--){
    94         L x,y; scanf("%lld%lld",&x,&y);
    95         L lca=getlca(x,y);
    96         printf("%lld
    ",max(jump(x,dep[x]-dep[lca]),jump(y,dep[y]-dep[lca])));
    97     }
    98 }
  • 相关阅读:
    JS document.execCommand实现复制功能(带你出坑)
    jquery动态添加删除一行数据示例
    SpringBoot SpEL表达式注入漏洞-分析与复现
    Fastjson 1.2.22-24 反序列化漏洞分析
    udf提权原理详解
    ZZCMS v8.2 前台Insert注入+任意文件删除
    安恒杯 3月线上个人赛WriteUp
    SQLI LABS Stacked Part(38-53) WriteUp
    【转】Ubuntu16.04安装docker
    安装部署k8s-版本-1.13
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10793002.html
Copyright © 2011-2022 走看看