第k短路
阿新 • • 發佈:2017-09-08
ont 找到 朝向 .... div bool sin eat cos
http://acm.pku.edu.cn/JudgeOnline/problem?id=2449
有向圖上求兩點st, ed間的第k短的路徑
emmm......
樸素的想法就是priority_queue,從原點出發向外探索,當取出終點k次時就得到第k短路
類似“bfs”的思想,缺陷是越往後狀態數越多
改進一下,這裏有個A*算法,比果體的搜索要好
在A*裏面我們通過優先展開到ed近的狀態,使搜索方向靠近答案,而不是一層一層全都展開
估價函數f=g+h f是估計的st到ed的距離,g是到達當前點已經點的花費,h是預計剩下的花費
h如果完全為真實值 那搜索就會筆直朝向答案前進沒有浪費,如果h不那麽準確,emmm問題不大,只是會晚點找到答案
我們表面上說h差不多就行,然而我們都知道,h的設計很重要
在這裏h可以取當前點的距離到ed距離 通過反向建邊,從ed跑一遍dijkstra可以預處理出距離數組
反向建邊值得好好體會,邊就在那裏,只是head和next的連接一正一反
還有個細節就是st==ed時給k++,不然還沒移動呢就有一次取出的計數了
#include<cstdio> #include<cstring> #include<queue> using namespace std; // f = g + h; const int maxn = 1e3+7, maxm = 1e5+7, INF = 0x3f3f3f3f; int head[maxn], rhead[maxn], vis[maxn], d[maxn], cur; struct edge{ int rv, v, w, nxt, rnxt; edge(){} edge(int rv, int v, int w, int nxt, int rnxt):rv(rv), v(v), w(w), nxt(nxt), rnxt(rnxt){} }e[maxm]; typedef pair<int, int>pi; struct state{ int g, h, v;// g cost h pending state(){} state(int g, int h, int v):g(g), h(h), v(v){} bool operator < (const state tmp)const{ return g + h > tmp.g + tmp.h; } };// greater<state> not defined void addedge(int u, int v, int w){ e[cur] = edge(u, v, w, head[u], rhead[v]); head[u] = cur; rhead[v] = cur++; } void dijkstra(int st){// distance from "st" memset(d, INF, sizeof(d)); memset(vis, 0, sizeof(vis)); priority_queue<pi, vector<pi>, greater<pi> >P; d[st] = 0; P.push(make_pair(0, st)); while(!P.empty()){ pi x = P.top(); P.pop(); int u = x.second, dis = x.first; if(vis[u]) continue; vis[u] = 1; for(int i = rhead[u]; ~i; i = e[i].rnxt){ int rv = e[i].rv, w = e[i].w, len = dis+w; if(d[rv] > len){ d[rv] = len; P.push(make_pair(d[rv], rv)); } } } } int Astar(int st, int ed, int k){ if(st == ed) k++; if(d[st] == INF) return -1; priority_queue<state>P; P.push(state(0, d[st], st)); while(!P.empty()){ state x = P.top(); P.pop(); int g = x.g, u = x.v; if(u == ed){ if(k > 1) k--; else return g; } for(int i = head[u]; ~i; i = e[i].nxt){ int v = e[i].v, w = e[i].w; P.push(state(g+w, d[v], v)); } } return -1; } int main(){ int n, m; while(~scanf("%d%d", &n, &m)){ cur = 0; memset(head, -1, sizeof(head)); memset(rhead, -1, sizeof(rhead)); while(m--){ int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); } int st, ed, k; scanf("%d%d%d", &st, &ed, &k); dijkstra(ed); printf("%d\n", Astar(st, ed, k)); } return 0; }
第k短路