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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
| for(int k=1;k<=p;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
```
当 p=n 时,该代码就是我们所熟知的 floyd,然而小 A 为了让代码跑的更快点,所以想减少 p 的值。
令 Di,j 为最小的非负整数 x,满足当 p=x 时,点 i 与点 j 之间的最短路被正确计算了。
现在你需要求 ∑ni=1∑nj=1Di,j,虽然答案不会很大,但为了显得本题像个计数题,你还是需要将答案对 998244353 取模后输出。
**Input**
第一行一个正整数 T(T≤30) 表示数据组数
对于每组数据:
第一行两个正整数 n,m(1≤n≤1000,m≤2000),表示点数和边数。
保证最多只有 5 组数据满足 max(n,m)>200
接下来 m 行,每行三个正整数 u,v,w 描述一条边权为 w 的边 (u,v),其中 1≤w≤109
**Output**
输出 T 行,第 i 行一个非负整数表示第 i 组数据的答案
### 思路
就是求最大松弛点中的最小值, 当时比赛的时候不管怎么样都不能顿悟, 还是太菜了呀。
### AC代码
```cpp
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <utility>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#define eps 1e-8
typedef long long ll;
const int N = 1e5 + 5;
typedef std::pair<ll, int> P;
const int INF = 0x3f3f3f3f;
const ll llINF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
struct edge{
int v;
ll w;
int ne;
}ed[N];
int head[1003];
bool vis[1003];
ll dis[1003];
int d[1003][1003];
int cnt, m, n;
void init(){
cnt = 0;
memset(head, -1, sizeof head);
memset(d, 0, sizeof d);
}
void addedge(int u, int v, ll w){
ed[cnt].v = v, ed[cnt].w = w;
ed[cnt].ne = head[u];
head[u] = cnt++;
}
std::priority_queue<P, std::vector<P> , std::greater<P> >q;
void dijk(int s){
memset(vis, false, sizeof vis);
for (int i = 1; i <= n; i++)
dis[i] = 1e18;
dis[s] = 0;
q.push(P(0, s));
while(!q.empty()){
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = true;
for (int i = head[u]; ~i; i = ed[i].ne){
int v = ed[i].v;
if (dis[v] > dis[u] + ed[i].w){
dis[v] = dis[u] + ed[i].w;
q.push(P(dis[v], v));
if (dis[v] == ed[i].w) {
d[s][v] = 0;
}
else {
d[s][v] = std::max(d[s][u], u);
}
}
else if (dis[v] == dis[u] + ed[i].w){
d[s][v] = std::min(d[s][v], std::max(u, d[s][u]));
}
}
}
}
int main(){
std::ios::sync_with_stdio(false);
// std::cin.tie(nullptr);
ll ans;
int t, u, v;
ll w;
std::cin >> t;
while(t--){
std::cin >> n >> m;
init();
for (int i = 0; i < m; i++){
std::cin >> u >> v >> w;
addedge(u, v, w);
addedge(v, u, w);
}
for (int i = 1; i <= n; i++)
dijk(i);
ans = 0;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
ans = (ans + d[i][j]) % mod;
}
}
std::cout << ans % mod << "\n";
}
return 0;
}
|