• luogu 2483 K短路 (可持久化左偏树)


    题面:

    题目大意:给你一张有向图,求1到n的第k短路

    $K$短路模板题

    假设整个图的边集为$G$

    首先建出以点$n$为根的,沿反向边跑的最短路树,设这些边构成了边集$T$

    那么每个点沿着树边走到点$n$,它对于答案的贡献为0

    我们加入一条非树边,它对于答案的贡献就是$delta(u,v)=dis[v]+e(u,v)-dis[u]$,即如果选择了这条边,这条路径的长度就会增加$delta(u,v)$

    那么一条路径$p$的总长度就是$dis_{min}+sumlimits_{ein p,ein G-T} delta(e)$

    我们现在要求出前$K$条总长度最小的路径长度,(即使在这道题里我们不知道K是多少)

    我们首先向一个堆中加入一条非树边,然后依次拓展,拓展的过程是这样的:

    每次从堆中取出一条边集$p$,然后有两种情况

    1.把末尾这条边替换成,这条边原来所在的边集里,边权大于等于它的一条边

    2.新加入一条,末尾这条边的终点$v$,在最短路树里的一个祖先所能扩展的一条最短的非树边

    这样扩展保证了每次新产生的边集贡献$geq $原来的边集贡献,保证了有序性

    且每次都选择最短的边集,保证了同一种边集不会重复讨论

    第二个操作需要找出最小的后继状态,而后继状态可能很多,想办法用数据结构维护

    在最短路树上每个点都维护反向非树边的集合,那么子节点也要包含父节点的集合,需要可持久化

    而对于第一个操作,我们需要一个有序表来扩展,所以要用到堆之类的东西

    可持久化可并堆!

    无非就是$merge$里每次合并都新建节点罢了

    第一个操作就是把最后一条边换成这条边在堆中的左右儿子

    第二个操作直接取堆顶即可

    这也是类似于普通$dijkstra$最短路的扩展过程

      1 #include <queue>
      2 #include <cmath>
      3 #include <vector>
      4 #include <cstdio>
      5 #include <cstring>
      6 #include <algorithm>
      7 #define N1 5010
      8 #define M1 200010
      9 #define S1 N1<<8
     10 #define ll long long 
     11 #define dd double
     12 using namespace std;
     13 const dd eps=1e-7;
     14 
     15 template <typename _T> void read(_T &ret)
     16 {
     17     ret=0; _T fh=1; char c=getchar();
     18     while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
     19     while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
     20     ret=ret*fh;
     21 }
     22 
     23 int n,m;
     24 struct Edge{
     25 int to[M1<<1],nxt[M1<<1],val[M1<<1],head[N1],cte; dd dis[M1<<1];
     26 void ae(int u,int v,dd d)
     27 {
     28     cte++; to[cte]=v; nxt[cte]=head[u];
     29     head[u]=cte; dis[cte]=d;
     30 }
     31 }e; 
     32 
     33 
     34 struct node1{
     35 int x; dd d;
     36 node1(int x,dd d):x(x),d(d){} node1(){}
     37 friend bool operator < (const node1 &s1,const node1 &s2)
     38 {
     39     return s1.d>s2.d;
     40 }
     41 };
     42 
     43 struct Heap{
     44 int ch[S1][2],h[S1],root0[N1],root1[N1],tot; node1 val[S1];
     45 int merge0(int x,int y)
     46 {
     47     if(!x||!y) return x+y;
     48     if(val[x]<val[y]) swap(x,y);
     49     ch[x][1]=merge0(ch[x][1],y);
     50     if(h[ch[x][0]]<h[ch[x][1]]) swap(ch[x][0],ch[x][1]);
     51     h[x]=h[ch[x][1]]+1;
     52     return x;
     53 }
     54 int merge1(int x,int y)
     55 {
     56     if(!x||!y) return x+y;
     57     if(val[x]<val[y]) swap(x,y);
     58     int nx=++tot; val[nx]=val[x]; ch[nx][0]=ch[x][0]; ch[nx][1]=ch[x][1]; h[nx]=h[x];
     59     ch[nx][1]=merge1(ch[x][1],y);
     60     if(h[ch[nx][0]]<h[ch[nx][1]]) swap(ch[nx][0],ch[nx][1]);
     61     h[nx]=h[ch[nx][1]]+1;
     62     return nx;
     63 }
     64 }h;
     65 
     66 priority_queue<node1>q;
     67 int use[N1]; dd dis[N1];
     68 void dijkstra()
     69 {
     70     node1 k; int x,j,v;
     71     q.push(node1(n,0)); dis[n]=0;
     72     for(j=1;j<n;j++) dis[j]=666666666;
     73     while(!q.empty())
     74     {
     75         k=q.top(); q.pop(); x=k.x; 
     76         if(use[x]) continue; use[x]=1;
     77         for(j=e.head[x];j;j=e.nxt[j])
     78         {
     79             v=e.to[j]; 
     80             if(dis[v]-eps>dis[x]+e.dis[j])
     81             {
     82                 dis[v]=dis[x]+e.dis[j];
     83                 q.push(node1(v,dis[v]));
     84             }
     85         }
     86     }
     87 }
     88 int fa[N1],de; dd la[N1];
     89 void dfs_tree(int x)
     90 {
     91     int j,v;
     92     if(fa[x]) h.root1[x]=h.merge1(h.root1[fa[x]],h.root0[x]);
     93     for(j=e.head[x];j;j=e.nxt[j])
     94     {
     95         v=e.to[j]; if(!e.val[j]) continue;
     96         dfs_tree(v);
     97     }
     98 }
     99 void build_tree()
    100 {
    101     int i,x,j,v;
    102     for(i=1;i<=n;i++) 
    103     {
    104         for(j=e.head[i];j;j=e.nxt[j])
    105         {
    106             v=e.to[j]; 
    107             if(!fa[v]&&fabs(dis[i]+e.dis[j]-dis[v])<eps)
    108                 e.val[j]^=1, fa[v]=i;
    109         }
    110     }
    111     for(x=1;x<=n;x++) 
    112     {
    113         for(j=e.head[x];j;j=e.nxt[j])
    114         {
    115             v=e.to[j]; if(e.val[j]) continue;
    116             h.val[++h.tot]=node1(x,dis[x]+e.dis[j]-dis[v]);
    117             h.root0[v]=h.merge0(h.root0[v],h.tot);
    118         }
    119     }
    120 }
    121 dd E;
    122 struct node2{
    123 int x,v; dd d,D;
    124 node2(int x,int v,dd d,dd D):x(x),v(v),d(d),D(D){} node2(){}
    125 friend bool operator < (const node2 &s1,const node2 &s2)
    126 {
    127     return s1.D>s2.D;
    128 }
    129 };
    130 priority_queue<node2>que;
    131 
    132 void debug()
    133 {
    134     int x=1; 
    135     while(fa[x]) printf("%d ",fa[x]), x=fa[x];
    136     puts("");
    137 }
    138 
    139 int main()
    140 {
    141     //freopen("testdata.in","r",stdin);
    142     scanf("%d%d%lf",&n,&m,&E);
    143     int i,j,k,x,y,v,xx,vv,ans=0; dd d,now,w; 
    144     for(i=1;i<=m;i++) 
    145     {
    146         read(x), read(y), scanf("%lf",&d);
    147         e.ae(y,x,d); 
    148     }
    149     dijkstra();
    150     build_tree();
    151     dfs_tree(n);
    152     node2 K;
    153     que.push(node2(0,1,0,0)); ans=0;
    154     //debug();
    155     while(!que.empty())
    156     {
    157         K=que.top(); que.pop(); x=K.x; v=K.v; E-=K.D+dis[1]; 
    158         //printf("%lf
    ",K.D+dis[1]);
    159         if(E>-eps) ans++; else break;
    160         if(h.root1[v]) 
    161         {
    162             j=h.root1[v]; vv=h.val[j].x; w=h.val[j].d;
    163             que.push(node2(j,vv,w,K.D+w));
    164         }
    165         if(h.ch[x][0])
    166         {
    167             j=h.ch[x][0]; vv=h.val[j].x; w=h.val[j].d;
    168             que.push(node2(j,vv,w,K.D-K.d+w));
    169         }
    170         if(h.ch[x][1])
    171         {
    172             j=h.ch[x][1]; vv=h.val[j].x; w=h.val[j].d;
    173             que.push(node2(j,vv,w,K.D-K.d+w));
    174         }
    175     }
    176     printf("%d
    ",ans);
    177     return 0;
    178 }
  • 相关阅读:
    LINQ to XML一些基本查询
    系统二级域名配置说明
    分布式文件系统部署Hadoop【转载】
    5 ways to instantly appear more confident
    hadoop Namenode和DataNode架构分析
    Employee burnout: Around the corner? Already here?
    阿里巴巴分布式服务框架 Dubbo 团队成员梁飞专访
    eclipse web项目 分多个源文件目录
    配置VS2008本地调试.NETFRAMEWORK源代码
    Google搜索指令大全
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10463965.html
Copyright © 2020-2023  润新知