最短路径条数统计【最短路】【题目】
1.我想到的是跑两边,第一遍先找最短距离,第二遍找到最短路径的条数
但是可以边找最短路径边找最短路径的条数
spfa:最短距离可能会多次更新,每次更新的时候cnt[i]数组也重新计数就好了(不是从0开始哦)
dijkstra:虽然第一次就找到了最短路径,但还没将点i加入源点集的时候并不知道当前i距离是最短的还是之后会被更新的,所以也需要不断更新cnt数组(dijkstra的方法可以有空写写,暑期集训的题我基本都是用spfa写的,不太好,还是要练一练dijkstra)
spfa的cnt[k]每次还要清零是为了个啥??

#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <vector> #include <queue> #include <sstream> #include <stack> #include <map> #include <ctime> #include <set> using namespace std; #define inf 0x3f3f3f3f #define mod 9987 const int N = 1e2+10; const int M = 1e4+10; int n, m; //与边相关 struct edge { int v, next, w; } e[M]; int p[N], eid; inline void Init_edge() { memset(p, -1, sizeof(p)); eid = 0; } void insert(int u, int v, int w) { e[eid].next = p[u]; e[eid].v = v; e[eid].w = w; p[u] = eid++; } //spfa int cnt[N]; int dis[N]; bool in[N]; inline void Init() { memset(dis, 0x3f, sizeof(dis)); memset(in, false, sizeof(in)); } void Spfa() { Init(); memset(cnt, 0, sizeof(cnt)); queue<int> q; q.push(1); dis[1] = 0; in[1] = true; cnt[1] = 1; int u; while(!q.empty()) { u = q.front(); q.pop(); in[u] = false; for(int i = p[u]; ~i; i = e[i].next) { int v = e[i].v, w = e[i].w; if(dis[u]+w < dis[v]) { cnt[v] = cnt[u]; dis[v] = dis[u]+w; if(!in[v]) { q.push(v); in[v] = true; } } else if(dis[u]+w == dis[v]) { cnt[v] += cnt[u]; } } } } //建图 inline void In() { cin >> n >> m; int u, v, w; for(int i = 1; i <= m; i++) { cin >> u >> v >> w; insert(u, v, w); } } //主函数 int main() { freopen("in.txt", "r", stdin); ios::sync_with_stdio(false); //建图 Init_edge(); In(); //spfa Spfa(); if(dis[n] < inf) { cout << dis[n] <<" "<<cnt[n]; } else cout <<"No answer"; return 0; }
3、如果搜索到的一条边的终点为n,那么我们应该跳过这一条边的搜索,而不是直接结束程序。 4、每次对取出来的点进行完搜索后,一定要将它的路径数清0,不然会出现重复统计。