P1608 路徑統計
阿新 • • 發佈:2018-11-02
真正的最短路計數問題
這道題就是傳說中的最短路計數問題了。
其實最短路計數就是在最短路演算法上面新增兩句話就完事了。
一句是在判斷有道路與當前最短路一樣長的時候,答案會變多。
一句是在更新最短路的時候,答案會變成從那個點開始的最短路。
所以就沒有問題了?
這道題不僅有重邊,還可能後面給你更小的邊!
解決方法有兩個:
乖乖用鄰接矩陣,寫一下基於矩陣的dijkstra。
用個鄰接矩陣來判斷下邊的關係,看看有相同起點終點的邊是否需要加進來。再換成鄰接表跑堆優化的dijkstra。
我用的是第二種。我不會寫矩陣的演算法除了floyd。
程式碼:
#include<cstdio> #include<cstring> #include<queue> const int maxn = 2005; struct Edges { int next, to, weight; } e[4000005]; int b[maxn][maxn]; int head[maxn], tot; int dist[maxn]; int cnt[maxn]; int n, m; struct Heapnodes { int d, u; bool operator < (const Heapnodes &rhs) const { return d > rhs.d; } }; int read() { int ans = 0, s = 1; char ch = getchar(); while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar(); return s * ans; } void link(int u, int v, int w) { e[++tot] = (Edges){head[u], v, w}; head[u] = tot; } void dijkstra() { memset(dist, 0x3f, sizeof dist); std::priority_queue<Heapnodes> heap; dist[1] = 0; heap.push((Heapnodes){dist[1], 1}); cnt[1] = 1; while(!heap.empty()) { Heapnodes x = heap.top(); heap.pop(); int d = x.d, u = x.u; if(d != dist[u]) continue; for(int i = head[u]; i; i = e[i].next) { int v = e[i].to; if(dist[u] + e[i].weight == dist[v]) cnt[v] += cnt[u]; if(dist[u] + e[i].weight < dist[v]) { dist[v] = dist[u] + e[i].weight; heap.push((Heapnodes){dist[v], v}); cnt[v] = cnt[u]; } } } } int main() { memset(b, 0x3f, sizeof b); n = read(), m = read(); while(m--) { int u = read(), v = read(), w = read(); if(b[u][v] > w) { link(u, v, w); b[u][v] = w; } } dijkstra(); if(dist[n] != 0x3f3f3f3f) printf("%d %d\n", dist[n], cnt[n]); else printf("No answer\n"); return 0; }