1. 程式人生 > >利用可持久化可並堆優化實現K短路

利用可持久化可並堆優化實現K短路

fff bre style 距離 end 直接 所有 利用 lse

本來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多行幸虧沒出什麽調不出來的錯誤,唉,菜啊

利用可持久化可並堆優化實現K短路