第k短路
Posted DearDongchen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第k短路相关的知识,希望对你有一定的参考价值。
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短路的主要内容,如果未能解决你的问题,请参考以下文章