HDU - 6705 path (求圖上不固定起終點的第k短路)
阿新 • • 發佈:2020-09-08
path hdu-6705
題意:給你一幅有向圖,給你q個數k ,問你在這幅圖上第k短的路徑有多長。
思路:首先有q個詢問,且沒有出現修改操作,考慮離線處理。然後我們可以用一個vector儲存所有的邊。並把每個節點的出邊按從小到大排序。接下來求出所有詢問的最大值maxk,然後我們只要求第1~maxk的短路即可。然後先把所有邊都存入一個set,並且這個set是按照路徑長短排序的。接下來保證這個set裡的元素有maxk個,然後用類似於Djikstra求最短路的方法不斷去set中的內容即可,第i次從set的頭部彈出的就是第i短路。
程式碼:
const int maxn=5e5+5; ll ans[maxn]; int n,m,k,cur[maxn],cnt=0; struct node{ int v;ll w; node (int v = 0, int w = 0): v(v), w(w) {} bool operator < (const node &b) const { return w<b.w; } }; vector<node>G[maxn]; struct Edge{ int u,v; ll w; int id; Edge(int u = 0, int v = 0, ll w = 0, int id = 0): u(u), v(v), w(w), id(id) {} bool operator <(const Edge &b)const{ if(w==b.w){ if(u==b.u){ if(v==b.v){ return id<b.id; }else{ return v<b.v; } }else{ return u<b.u; } }else{ return w<b.w; } } bool operator == (const Edge &b) const { return w == b.w && u == b.u && v == b.v && id == b.id; } }; int main() { int T; cin>>T; while(T--){ scanf("%d %d %d",&n,&m,&k); for(int i=1;i<=n;i++){ G[i].clear(); } set<Edge>st; st.clear(); cnt=0; for(int i=1;i<=m;i++){ int u,v; ll w; scanf("%d%d%lld",&u,&v,&w); G[u].push_back(node(v,w)); st.insert(Edge(u,v,w,++cnt)); } for(int i=1;i<=n;i++){ sort(G[i].begin(),G[i].end()); } int maxk=0; for(int i=1;i<=k;i++){ scanf("%d",&cur[i]); maxk=max(maxk,cur[i]); } while(st.size()>maxk){ st.erase(st.end()); } for(int i=1;i<=maxk;i++){ Edge now=*st.begin(); st.erase(st.begin()); ans[i]=now.w; if(i==maxk)break; int u=now.v; for(int j=0;j<G[u].size();j++){ int v=G[u][j].v; ll w=G[u][j].w; if(st.size()+i<maxk){ st.insert(Edge(u,v,now.w+w,++cnt)); }else{ set<Edge>::iterator it = st.end(); it--; Edge last=*it; if(last.w>w+now.w){ st.erase(it); st.insert(Edge(u,v,w+now.w,++cnt)); }else{ break; } } } } for(int i=1;i<=k;i++){ printf("%lld\n",ans[cur[i]]); } } return 0; }