1 条题解

  • 0
    @ 2025-7-1 18:42:04
    • 题意 -  求有向图中第k短路(可重复走).

    • 思路 -   A ∗ 算法的讲解: http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx    本题中 A ∗ 的运用我觉得就是在优化BFS, 队列中的元素(x)我们设有ST[x]表示从起点出发到 x 点已走的路径, EN[x]表示 x 距离终点的最短路径. 则队列中元素按G[x] = ST[x]+EN[x]从小到大排列, 每次取出最小的G[x], 将 x 可以到达的点插入队列中(他们的路径是从 x 走到的, 依靠 G[x] 来更新这些点的G), 直到终点被取出第 k 次时有解(说明找到了 k 种不同路径通向终点).  EN[x]要用反向边预处理最短路.    细节见代码.

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define ft first
    #define sd second
    using namespace std;
    
    typedef pair<int, int> pii;
    const int N = 1e3 + 5;
    const int M = 1e5 + 5;
    
    int TO[M], NXT[M], V[M], HD[N];
    int re_TO[M], re_NXT[M], re_V[M], re_HD[N];
    int DIS[N], VIS[N];
    int n, m;
    int sz, re_sz;
    
    struct ASTAR {
    	int v, pos;
    	bool operator < (const ASTAR &tmp) const {
    		return DIS[v] + pos > DIS[tmp.v] + tmp.pos;
    	}
    };
    
    void add(int x, int y, int v) {
    	TO[++re_sz] = y; V[re_sz] = v;
    	NXT[re_sz] = HD[x]; HD[x] = re_sz;
    }
    
    void re_add(int x, int y, int v) {
    	re_TO[++sz] = y; re_V[sz] = v;
    	re_NXT[sz] = re_HD[x]; re_HD[x] = sz;
    }
    
    void dijkstra(int x) {
    	priority_queue<pii, vector<pii>, greater<pii> >Q;
    	memset(DIS, 0x3f, sizeof (DIS));
    	DIS[x] = 0;
    	pii st = make_pair(0, x);
    	Q.push(st);
    	while (!Q.empty()) {
    		pii x = Q.top();
    		Q.pop();
    		int u = x.sd;
    		if (VIS[u]) continue;
    		VIS[u] = 1;
    		for (int i = re_HD[u]; i; i = re_NXT[i]) {
    			int v = re_TO[i];
    			if (!VIS[v] && DIS[v] > DIS[u] + re_V[i]) {
    				DIS[v] = DIS[u] + re_V[i];
    				pii y = make_pair(DIS[v], v);
    				Q.push(y);
    			}
    		}
    	}
    }
    
    int astar(int x, int y, int k) {
    	if (x == y) k ++; //注意起点终点相同时, 一开始只有起点在队列中, 会被多计算一次.
    	priority_queue<ASTAR>Q;
    	ASTAR st;
    	st.v = x; st.pos = 0;
    	Q.push(st);
    	while (!Q.empty()) {
    		ASTAR x = Q.top();
    		Q.pop();
    		int u = x.v;
    		if (u == y) {
    			-- k;
    			if (!k)
    				return x.pos;
    		}
    		for (int i = HD[u]; i; i = NXT[i]) {
    			int v = TO[i];
    			ASTAR w;
    			w.v = v; w.pos = x.pos + V[i];
    			Q.push(w);
    		}
    	}
    	return -1;
    }
    
    int main() {
    	int x, y, v;
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= m; ++ i) {
    		scanf("%d%d%d", &x, &y, &v);
    		add(x, y, v);
    		re_add(y, x, v);
    	}
    	scanf("%d%d%d", &x, &y, &v);
    	dijkstra(y);
    	if (DIS[x] == 0x3f3f3f3f) {
    		printf("%d\n", -1); //注意起点终点不连通的情况
    		return 0;
    	}
    	printf("%d\n", astar(x, y, v));
    	return 0;
    }
    
    
    • 1

    信息

    ID
    1451
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    5
    已通过
    1
    上传者