城堡

    普通的的图论题

思路:先将边读入,建图。

对图跑一遍SPFA ,找出 点1 到各点的最短路。

再跑一遍SPFA , 不过这次找的是树中 与 点i 相连接 并且 当前扫描点的dis 值 加上 i 到当前点的边权等于i 点dis值的边的数量

最后运用什么乘法原理,即    问题的答案是由m 个答案构成 ,第一步的答案为n1 种,第二步为n2 种, 第三步为n3种 ,则第n步的答案 有 m * n种(大意)

把答案乘起来。

#include <iostream>
#include <cstdio>
#include <cstring>
#define Max 1000000
#define mod 2147483647
#define INF 100000000
using namespace std;
int N, M;
int Total;
int head [Max / 1000 | 1];
int dis [Max / 1000 | 1], queue [Max / 1000 | 1];
bool visit [Max / 1000 | 1];
long long Answer , count [Max / 1000 | 1];
struct node
{
    int next;
    int node;
    int worth;
}Edge [Max];
inline void AddEdge (int x, int y, int w)   // 加边 
{
        Edge [++Total].next = head [x];
        head [x] = Total;
        Edge [Total].node = y;
        Edge [Total].worth = w; 
}
inline int Judge (int &x)
{
    return x = x + 1 == N ? 0 : x + 1;   //如果x + 1 == n 表明已经到了终点, 再指回起点 
}
inline void SPFA (int x)   //  SPFA最短路  
{
    int head_cur = 0, tail = 0;
    for (int i = 1; i <= N; i++)
        dis [i] = INF;
    dis [x] = 0;
    visit [x] = true;
    queue [Judge (tail)] = x;
    while (head_cur != tail)
    {
        int cur = queue [Judge (head_cur)];
        visit [cur] = false;
        for (int i = head [cur]; i; i = Edge [i].next)
        {
            int node = Edge [i].node ;
            if (dis [node] > dis [cur] + Edge [i].worth)
            {
                dis [node] = dis [cur] + Edge [i].worth;
                if (! visit [node])
                {
                    visit [node] = true;
                    queue [Judge (tail)] = node;
                }
            }
        }
    }
}
int main()
{
    ios :: sync_with_stdio (false);
    cin >> N >> M;
    int x, y, w;
    for (int i = 1; i <= M; i++)
    {
        cin >> x >> y >> w;
        AddEdge (x, y, w);        //加到图中 
        AddEdge (y, x, w);          //因为是无向图,所以 (x, y)(y, x) 都要建边 
    }
    SPFA (1);               // 跑一遍SPFA找出 点1 到各点的最短路 
    int head_cur = 0, tail = 0;   
    queue [Judge (tail)] = 1;
    visit [1] = true;
    count [1] = 1;               // 接下来 再跑一遍 SPFA,找出树中的最短路  
    while (head_cur != tail)
    {
        int cur = queue [Judge (head_cur)];
        for (int i = head [cur]; i; i = Edge [i].next)
        {
            int node = Edge [i].node;
            if (dis [node] == dis [cur] + Edge [i].worth )
            {
                count[node]++;   // 记录 与i点相连接 并且 当前扫描的点的dis值 加上 边权 等于 i点 的dis值 的 边的数量 
                if (count [node] >= mod)
                    count [node] -= mod;
                if (!visit [node])
                {
                    queue [Judge (tail)] = node;
                    visit [node] = true;
                }
            } 
        }
    }
    Answer = 1;
    for (int i = 1; i <= N; i++)
    {
        Answer *= count [i];         //利用  X X 乘法原理 , 把每个点满足的数量 乘起来 ,即为答案 
          if (Answer >= mod) 
            Answer %= mod;
    }
    printf ("%d
", (int) Answer);
    return 0;
}
原文地址:https://www.cnblogs.com/ZlycerQan/p/6060130.html