城堡
普通的的图论题
思路:先将边读入,建图。
对图跑一遍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\n", (int) Answer); return 0; }
myj 吊打我Orz,xxy 捆起来打我Orz,myl 文化课上天Orz, lrh 姿势水平敲高Orz, hkd 特别胖Orz%%%,cys 智商感人Orz,syl zz专业Orz,我没有学上, 我们未来一片光明