1. 程式人生 > >第k短路

第k短路

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短路