zoukankan      html  css  js  c++  java
  • BZOJ2725: [Violet 6]故乡的梦

    $n leq 2e5,m leq 2e5,q leq 2e5$,$n,m$的图给固定的$s,t$,以及$q$个询问,每次问删掉某条边之后问$s$到$t$的最短路。

    首先喷一波,出题人语文太差了,这么美的题目居然潦草两句带过背景,描述题目也毫无趣味,差评!(本题分类:语文)

    方法一:把图载到一个可控的数据结构上进行信息维护。删边之后,如果删掉的不是$s$到$t$的最短路,那直接输出最短路,否则,可以观察到一条非最短路边$w(x,y)$的贡献是$ds(x)+w(x,y)+dt(y)$,其中$ds,dt$表示起点到其最短路和终点到其最短路。

    好的那把最短路树建出来吧,然后把这些边的贡献载到点上,相当于链取$min$,单点查询。

    细节:

    对一个在$z$处的询问查询它爸爸那条边断掉的情况,在其子树中,如果$lca(x,z)$深度比$lca(y,z)$大,那么$ds(x)+w(x,y)+dt(y)$是没贡献的,因为这个贡献实际上是这样的:$s->lca(x,z)->x->y->lca(y,z)->t$。

    然后链取$min$改成子树标记,用线段树合并维护之。

    结果:慢,丑。

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 #include<queue>
      6 //#include<math.h>
      7 //#include<time.h>
      8 #include<assert.h>
      9 //#include<complex>
     10 #include<algorithm>
     11 using namespace std;
     12 
     13 int n,m,s,t,q;
     14 #define LL long long
     15 #define maxn 200011
     16 #define maxm 400011
     17 struct Edge{int to; int v,next;};
     18 int fa[maxn],ll[maxn],rr[maxn],anc[maxn][19],dep[maxn],Time;
     19 struct qnode
     20 {
     21     LL v; int id;
     22     bool operator > (const qnode &b) const {return v>b.v;}
     23 };
     24 priority_queue<qnode,vector<qnode>,greater<qnode> > que;
     25 struct Graph
     26 {
     27     Edge edge[maxm]; int first[maxn],le;
     28     Graph() {le=2;}
     29     void in(int x,LL y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
     30     void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);}
     31     void dijkstra(LL *dis,int s)
     32     {
     33         que.push((qnode){0,s});
     34         for (int i=1;i<=n;i++) dis[i]=1e18; dis[s]=0; fa[s]=0;
     35         while (!que.empty())
     36         {
     37             int now=que.top().id; LL d=que.top().v; que.pop();
     38             if (dis[now]!=d) continue;
     39             for (int i=first[now];i;i=edge[i].next)
     40             {
     41                 Edge &e=edge[i];
     42                 if (dis[e.to]>dis[now]+e.v)
     43                 {
     44                     dis[e.to]=dis[now]+e.v;
     45                     fa[e.to]=now;
     46                     que.push((qnode){dis[e.to],(int)e.to});
     47                 }
     48             }
     49         }
     50     }
     51     void dfs(int x)
     52     {
     53         anc[x][0]=fa[x]; ll[x]=++Time; dep[x]=dep[fa[x]]+1;
     54         for (int i=first[x];i;i=edge[i].next) dfs(edge[i].to);
     55         rr[x]=Time;
     56     }
     57 }g,tree,eve,fl;
     58 void makeanc()
     59 {
     60     for (int j=1;j<=18;j++)
     61         for (int i=1;i<=n;i++)
     62             anc[i][j]=anc[anc[i][j-1]][j-1];
     63 }
     64 int lca(int x,int y)
     65 {
     66     if (dep[x]<dep[y]) {int t=x; x=y; y=t;}
     67     for (int j=18;j>=0;j--) if (dep[anc[x][j]]>=dep[y]) x=anc[x][j];
     68     if (x==y) return x;
     69     for (int j=18;j>=0;j--) if (anc[x][j]!=anc[y][j]) x=anc[x][j],y=anc[y][j];
     70     return anc[x][0];
     71 }
     72 LL diss[maxn],dist[maxn];
     73 LL ans[maxn],lisa[maxm]; int li=0;
     74 
     75 int root[maxn];
     76 struct smt
     77 {
     78     struct Node
     79     {
     80         int ls,rs;
     81         int cnt,Min;
     82     }a[maxn*18];
     83     int n,size;
     84     void clear(int m) {size=0; n=m; a[0].Min=n+1;}
     85     void up(int x)
     86     {
     87         int &p=a[x].ls,&q=a[x].rs;
     88         a[x].Min=min(a[p].Min,a[q].Min);
     89     }
     90     void New(int &x) {x=++size; a[x].ls=a[x].rs=0; a[x].cnt=0; a[x].Min=n+1;}
     91     void insert(int &x,int L,int R,int pos,int v)
     92     {
     93         if (!x) New(x);
     94         if (L==R)
     95         {
     96             a[x].cnt+=v;
     97             if (a[x].cnt>0) a[x].Min=pos;
     98             else a[x].Min=n+1;
     99             return;
    100         }
    101         int mid=(L+R)>>1;
    102         if (pos<=mid) insert(a[x].ls,L,mid,pos,v); else insert(a[x].rs,mid+1,R,pos,v);
    103         up(x);
    104     }
    105     void insert(int &x,int pos,int v) {insert(x,1,n,pos,v);}
    106     void combine(int &x,int y,int L,int R)
    107     {
    108         if (!x || !y) {x=x+y; return;}
    109         if (L==R) {a[x].cnt=a[x].cnt+a[y].cnt; if (a[x].cnt>0) a[x].Min=L; else a[x].Min=n+1; return;}
    110         int mid=(L+R)>>1;
    111         combine(a[x].ls,a[y].ls,L,mid);
    112         combine(a[x].rs,a[y].rs,mid+1,R);
    113         up(x);
    114     }
    115     void combine(int &x,int y) {combine(x,y,1,n);}
    116 }smt;
    117 
    118 void go(int x,int fa)
    119 {
    120     root[x]=0;
    121     for (int i=fl.first[x];i;i=fl.edge[i].next)
    122     {
    123         Edge &e=fl.edge[i];
    124         smt.insert(root[x],e.to,e.v);
    125     }
    126     for (int i=tree.first[x];i;i=tree.edge[i].next)
    127     {
    128         Edge &e=tree.edge[i]; if (e.to==fa) continue;
    129         go(e.to,x); smt.combine(root[x],root[e.to]);
    130     }
    131     for (int i=eve.first[x];i;i=eve.edge[i].next)
    132     {
    133         Edge &e=eve.edge[i];
    134         ans[e.to]=lisa[smt.a[root[x]].Min];
    135     }
    136 }
    137 
    138 int lx[maxm],ly[maxm];
    139 int main()
    140 {
    141     scanf("%d%d",&n,&m);
    142     for (int i=1,x,y,v;i<=m;i++) scanf("%d%d%d",&x,&y,&v),g.insert(x,y,v);
    143     scanf("%d%d",&s,&t);
    144     g.dijkstra(dist,t); g.dijkstra(diss,s);
    145     for (int i=1;i<=n;i++) if (fa[i]) tree.in(fa[i],i,0);
    146     tree.dfs(s); makeanc();
    147     for (int i=2;i<g.le;i+=2)
    148     {
    149         int x=g.edge[i].to,y=g.edge[i^1].to; lx[i]=lca(x,t),ly[i]=lca(y,t);
    150         if (fa[x]==y || fa[y]==x) continue;
    151         LL tmp=diss[x]+dist[y]+g.edge[i].v;
    152         if (dep[ly[i]]>dep[lx[i]]) {lisa[++li]=tmp;}
    153         tmp=diss[y]+dist[x]+g.edge[i].v;
    154         if (dep[lx[i]]>dep[ly[i]]) {lisa[++li]=tmp;}
    155         assert(li<maxm);
    156     }
    157     lisa[0]=-1e18; sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1; lisa[li+1]=1e18;
    158     smt.clear(li);
    159     for (int i=2;i<g.le;i+=2)
    160     {
    161         int x=g.edge[i].to,y=g.edge[i^1].to;
    162         if (fa[x]==y || fa[y]==x) continue;
    163         LL tmp=diss[x]+dist[y]+g.edge[i].v; int tt=lower_bound(lisa+1,lisa+1+li,tmp)-lisa;
    164         if (dep[ly[i]]>dep[lx[i]]) {fl.in(y,tt,1); fl.in(x,tt,-1);}
    165         tmp=diss[y]+dist[x]+g.edge[i].v; tt=lower_bound(lisa+1,lisa+1+li,tmp)-lisa;
    166         if (dep[lx[i]]>dep[ly[i]]) {fl.in(x,tt,1); fl.in(y,tt,-1);}
    167     }
    168     
    169     scanf("%d",&q);
    170     for (int i=1,x,y;i<=q;i++)
    171     {
    172         scanf("%d%d",&x,&y);
    173         if (fa[x]!=y && fa[y]!=x) ans[i]=diss[t];
    174         else if (ll[x]<=ll[t] && ll[t]<=rr[x] && ll[y]<=ll[t] && ll[t]<=rr[y])
    175         {
    176             if (fa[x]==y) eve.in(x,i,0);
    177             else eve.in(y,i,0);
    178         }
    179         else ans[i]=diss[t];
    180     }
    181     for (int i=tree.first[s];i;i=tree.edge[i].next)
    182     {
    183         Edge &e=tree.edge[i];
    184         if (ll[e.to]<=ll[t] && ll[t]<=rr[e.to]) {go(e.to,s); break;}
    185     }
    186     for (int i=1;i<=q;i++) printf(ans[i]==1e18?"Infinity
    ":"%lld
    ",ans[i]);
    187     return 0;
    188 }
    View Code

    方法二:可以发现刚刚的一系列行为都在$s->t$这条链上进行。实际上一条边$w(x,y)$的贡献可以看成:$s->s'->x->y->t'->t$,因此$s'$到$t'$之间的路都可以被贡献到,可以区间打标记。维护一条链比树上操作要方便许多。区间取$min$单点查询,可以线段树,也可排序+并查集。

    代码?略。

  • 相关阅读:
    idea实现快捷批量修改替换
    接口自动化测试:利用环境变量管理测试环境的切换
    接口自动化测试:pytest自定义fixture传参request
    接口自动化测试:python连接mysql方法封装
    接口自动化测试:yaml文件中变量替换
    接口自动化测试:测试数据生成的一个小技巧
    接口自动化测试:抓包方式理解三次握手与四次挥手
    selenium相关:selenium grid的简单用法
    APP测试学习:弱网测试
    APP测试学习:耗电量测试
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8527312.html
Copyright © 2011-2022 走看看