利用可持久化可并堆优化实现K短路

本来A*就可以搞定的题,为了怕以后卡复杂度,找了个这么个方法

现阶段水平不够就不补充算法分析部分了

对于图G,建立一个以终点t为起点的最短路径构成的最短路径树
(就是反着跑一遍最短路,然后对于一个不为终点的点v,v到终点t的最短路径上(任选一条)v的后继结点为v的父亲,就形成了一棵树)
然后对于所有点,定义其不在最短路径树上的出边的f值为:f[e] = l[e] + dis[e.tail] - dis[e.head] ,就是走这条边,走到t需要多绕的距离
那么我们只要找到第k小的这种边的序列就得到解了
那么我们维护按权值一个从小到大的优先队列,每次从队头取出一个序列q,设q的最后一条边e的head为u,tail为v
我们可以选择在序列的末尾加上v到t的所有路径上非树边的最小的得到一个新的序列q1
或者选择u到t的所有路径上所有非树边中e的后继(没用过的边中最小的)替换e得到q2,将q1,q2都塞进优先队列,重复k次,
可是怎么才能尽快知道一个节点v到t的所有路径上的非树边最小的一个呢?
打个可持久化的可并堆就没问题了,每个点合并他到根的路径上所有非树出边,然后对于找e的后继替换e的操作,直接找e的两个孩子就行了

本题难度爆表,低级图论和高级数据结构的大综合

直接上代码了,以后学的多了再回过头来看方法

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<queue>
  5 using namespace std;
  6 const int maxn=8005;  //为啥开这么大??? 
  7 const int maxm=100005;
  8 const int INF=0x7fffffff;
  9 int n,m,cnt,cntf,st,ed,k,tot,tp;
 10 bool vi[maxn];
 11 int g[maxn],gf[maxn],dis[maxn],_next[maxn],root[maxn],sta[maxn];
 12 struct Edge
 13 {
 14     int u,v,w,f,next;
 15     bool vis,flag;
 16 }e[maxm];
 17 struct Edgef
 18 {
 19     int t,w,next;
 20 }ef[maxm];
 21 
 22 void addedge(int x,int y,int z)
 23 {
 24     cnt++;
 25     e[cnt].u=x;e[cnt].v=y;e[cnt].w=z;
 26     e[cnt].next=g[x];g[x]=cnt;
 27     e[cnt].vis=0;
 28 }
 29 void addedgef(int x,int y,int z)
 30 {
 31     cntf++;
 32     ef[cntf].t=y;ef[cntf].w=z;
 33     ef[cntf].next=gf[x];gf[x]=cntf;
 34 }
 35 
 36 struct Node
 37 {
 38     int lc,rc,dis,c,y;
 39 }tr[maxn*100];
 40 int newnode(int c,int y)
 41 {
 42     tot++;
 43     tr[tot].lc=tr[tot].rc=0;
 44     tr[tot].dis=0;
 45     tr[tot].c=c;
 46     tr[tot].y=y;
 47     return tot;
 48 }
 49 int merge(int x,int y)
 50 {
 51     //cout<<x<<" "<<y<<endl;
 52     if(x==0||y==0) return x|y;
 53     if(tr[x].c>tr[y].c) swap(x,y);
 54     int ret=++tot;
 55     tr[ret]=tr[x];
 56     int k=merge(tr[ret].rc,y);
 57     if(tr[tr[ret].lc].dis<=tr[k].dis) swap(tr[ret].lc,k);
 58     tr[ret].rc=k;
 59     tr[ret].dis=tr[tr[ret].lc].dis+1;
 60     return ret;
 61 }
 62 struct HeapNode
 63 {
 64     int x,d;
 65 };
 66 bool operator <(HeapNode x,HeapNode y)
 67 {
 68     return x.d>y.d;
 69 }
 70 priority_queue<HeapNode> q;
 71 
 72 struct Graph
 73 {
 74     int u,x,d;
 75 };
 76 bool operator < (Graph x,Graph y)
 77 {
 78     return x.d>y.d;
 79 };
 80 priority_queue<Graph> Q;
 81 void getdis()
 82 {
 83     dis[ed]=0;
 84     HeapNode temp;
 85     temp.x=ed;temp.d=0;
 86     q.push(temp);
 87     while(!q.empty())
 88     {
 89         HeapNode x=q.top();q.pop();
 90         if(dis[x.x]<x.d) continue;
 91         for(int tmp=gf[x.x];tmp;tmp=ef[tmp].next)
 92         {
 93             int y=ef[tmp].t;vi[y]=1;
 94             if(dis[y]>x.d+ef[tmp].w)
 95             {
 96                 dis[y]=x.d+ef[tmp].w;
 97                 temp.x=y;temp.d=dis[y];
 98                 q.push(temp);
 99             }
100         }
101     }
102 }
103 void solve(int x)
104 {
105     if(x==ed)
106     {
107         for(int tmp=g[x];tmp;tmp=e[tmp].next)
108         {
109             int y=e[tmp].v;
110             if(e[tmp].flag==0) continue;
111             if(e[tmp].vis==0)
112             {
113                 root[x]=merge(root[x],newnode(e[tmp].f,e[tmp].v));
114             }
115         }
116         return;
117     }
118     for(int tmp=g[x];tmp;tmp=e[tmp].next)
119     {
120         int y=e[tmp].v;
121         if(e[tmp].flag==0) continue;
122         if(e[tmp].vis==0)
123             root[x]=merge(root[x],newnode(e[tmp].f,e[tmp].v));
124         else root[x]=merge(root[x],root[y]);
125     }
126 }
127 int main()
128 {
129     int u,v,w;
130     scanf("%d%d",&n,&m);
131     for(int i=1;i<=m;i++)
132     {
133         scanf("%d%d%d",&u,&v,&w);
134         addedge(u,v,w);
135         e[cnt].flag=1;
136         addedgef(v,u,w);
137     }
138     scanf("%d%d%d",&st,&ed,&k);
139     if(st==ed) k++;
140     
141     for(int i=1;i<=n;i++)
142         dis[i]=INF,vi[i]=0;
143     getdis();
144     
145     if(k==1)
146     {
147         if(vi[st]) printf("%d\n",dis[st]);
148         else printf("-1\n");
149         return 0;
150     }
151     for(int i=1;i<=cnt;i++)
152     {
153         e[i].f=e[i].w-dis[e[i].u]+dis[e[i].v];
154         if(dis[e[i].v]==INF) e[i].flag=0;
155     }
156     for(int i=1;i<=n;i++)
157     {
158         if(i==ed) continue;
159         for(int tmp=g[i];tmp;tmp=e[tmp].next)
160         {
161             v=e[tmp].v;
162             if(!e[tmp].flag) continue;
163             if(dis[i]==dis[v]+e[tmp].w)
164             {
165                 e[tmp].vis=1;
166                 _next[i]=v;
167                 break;
168             }
169         }
170     }
171     memset(root,0,sizeof(root));
172     tot=0;
173     for(int i=1;i<=n;i++)
174         if(!root[i])
175         {
176             if(dis[i]==INF) continue;
177             sta[tp=1]=i;
178             while(1)
179             {
180                 u=sta[tp];
181                 if(u==ed) break;
182                 if(!root[_next[u]]) sta[++tp]=_next[u];
183                 else break;
184             }
185             while(tp)
186             {
187                 solve(sta[tp]);
188                 tp--;
189             }
190         }
191     k-=2;
192     Graph ss;
193     ss.u=st;ss.d=tr[root[st]].c;ss.x=root[st];
194     Q.push(ss);
195     while(k--)
196     {
197         Graph tmp=Q.top();Q.pop();
198         if(tmp.u==0)
199         {
200             printf("-1\n");
201             return 0;
202         }
203         if(tr[tmp.x].lc)
204         {
205             Graph tmp1;
206             tmp1.u=tmp.u;
207             tmp1.d=-tr[tmp.x].c;
208             tmp1.x=merge(tr[tmp.x].lc,tr[tmp.x].rc);
209             tmp1.d+=tr[tmp1.x].c+tmp.d;
210             Q.push(tmp1);
211         }
212         Graph tmp2;
213         tmp2.u=tr[tmp.x].y;
214         tmp2.d=tmp.d+tr[root[tmp2.u]].c;
215         tmp2.x=root[tmp2.u];
216         Q.push(tmp2);
217     }
218     Graph ans=Q.top();
219     if(ans.u==0)
220     {
221         printf("-1\n");
222         return 0;
223     }
224     if(vi[st]) printf("%d\n",dis[st]+ans.d);
225     else printf("-1\n");
226     return 0;
227 }

200多行幸亏没出什么调不出来的错误,唉,菜啊

猜你喜欢

转载自www.cnblogs.com/aininot260/p/9456891.html