數據結構&圖論: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多行幸虧沒出什么調不出來的錯誤,唉,菜啊


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM