POJ 3463 - Sightseeing
http://acm.pku.edu.cn/JudgeOnline/problem?id=3463
求最短路和比最短路多一的路的个数
主体还是dijkstra。其实dijkstra有种动态规划的味道,仔细理解一下然后动态规划出次短路的长以及个数
开数组d[n][2],cnt[n][2]。[0]表示最短路, [1]表示次短路
计d[u]+w 为 len
1⃣️len < d[v][0]
len为新的最短路长 如果d[v][0]已经有值, 把这个值赋给次短路。
2⃣️len == d[v][0]
更新cnt[v][0]计数
3⃣️len < d[v][1]
len为新的次短路长
4⃣️len == d[v][1]
更新cnt[v][1]计数
最短和次短的状态都在一个优先队列里,然而不会出错,要在“状态”里加上flag变量记录这是个最短还是次短
#include<cstdio> #include<queue> #include<cstring> using namespace std; typedef long long ll; const int maxn = 1007, maxm = 10007; const int INF = 0x3f3f3f3f; struct edge{ int v, nxt, w; }e[maxm]; int head[maxn], vis[maxn][2], cnt[maxn][2], n, cur = 0; int d[maxn][2]; int st, ed; struct state{ int flag, dis, node; state(){} state(int a, int b, int c):flag(a), dis(b), node(c){} bool operator < (const state& S)const{ return dis > S.dis; } }; void addedge(int u, int v, int w){ e[cur].v = v; e[cur].w = w; e[cur].nxt = head[u]; head[u] = cur++; } void dijkstra(int st){ memset(d, INF, sizeof(d)); memset(vis, 0, sizeof(vis)); memset(cnt, 0, sizeof(cnt)); d[st][0] = 0; cnt[st][0] = 1; priority_queue<state> Q; state seed(0, 0, st); Q.push(seed); while(!Q.empty()){ state tmp = Q.top(); Q.pop(); int flag = tmp.flag, dis = tmp.dis, u = tmp.node; if(vis[u][flag]) continue; vis[u][flag] = 1; for(int i = head[u]; ~i; i = e[i].nxt){ int v = e[i].v, w = e[i].w, len = w + dis; if(len < d[v][0]){ if(d[v][0] != INF){ d[v][1] = d[v][0]; cnt[v][1] = cnt[v][0]; state newst(1, d[v][1], v); Q.push(newst); } d[v][0] = len; cnt[v][0] = cnt[u][flag]; state newst(0, d[v][0], v); Q.push(newst); } else if(len == d[v][0]){ cnt[v][0] += cnt[u][flag]; } else if(len < d[v][1]){ d[v][1] = len; cnt[v][1] = cnt[u][flag]; state newst(1, d[v][1], v); Q.push(newst); } else if(len == d[v][1]){ cnt[v][1] += cnt[u][flag]; } } } } int main(){ int t; scanf("%d", &t); while(t--){ memset(head, -1, sizeof(head)); cur = 0; int m; scanf("%d%d", &n, &m); while(m--){ int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); } scanf("%d%d", &st, &ed); dijkstra(st); int ans = cnt[ed][0]; if(d[ed][1] == d[ed][0] + 1){ ans += cnt[ed][1]; } printf("%d ", ans); } return 0; }