题目
link
题解
看到这个题,很像dp
但是它可能有环,所以不能dp。又因为都是正数,可以考虑用dijkstra的形式来做“dp”
dijkstra
需要注意的是,做dijkstra的时候需要注意一条边x->y
只有在x
和y
都确定了最小值的前提下才能够更新其他点,否则出现有些点生下来就是最小值的时候就会被重复计算方案数目。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include<bits/stdc++.h>
using namespace std;
const int N = 1100; int dis[N]; bool vis[N]; int num[N], g[N][N], n; int main() { scanf("%d", &n); for(int i = 1;i <= n;i++) scanf("%d", &dis[i]); int a, b, c; for(int i = 1;i <= n;i++) num[i] = 1; while(scanf("%d%d%d", &a, &b, &c) != EOF) { a++, b++; g[a][b] = g[b][a] = c + 1; } dis[0] = 0x3f3f3f3f; while(1) { int x = 0; for(int i = 1;i <= n;i++) { if(!vis[i] && dis[i] < dis[x]) x = i; } if(x == 0) { break; } vis[x] = 1; for(int y = 1;y <= n;y++) { if(g[x][y] == 0 || !vis[y]) continue; if(dis[g[x][y]] == dis[x] + dis[y]) { num[g[x][y]] += num[x] * num[y]; } else if(dis[g[x][y]] > dis[x] + dis[y]) { dis[g[x][y]] = dis[x] + dis[y]; num[g[x][y]] = num[x] * num[y]; } } } cout << dis[1] << " " << num[1]; return 0; }
|
spfa
sdsc 2022 day6课件有讲