最短路径条数统计【最短路】【题目】

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;
}
因此的错误代码

 

spfa两个要点

3、如果搜索到的一条边的终点为n,那么我们应该跳过这一条边的搜索,而不是直接结束程序。

4、每次对取出来的点进行完搜索后,一定要将它的路径数清0,不然会出现重复统计。

 

posted @ 2021-06-29 19:13  bear_xin  阅读(215)  评论(0)    收藏  举报