原题传送门
f l o y d floyd floyd算出两两之间最短路 d i s t dist dist以及最短路方案数 n u m num num
对于两个城市 j , k j,k j,k, i i i是 j 到 k j到k j到k最短路非走不可的城市的充要条件是 d i s t j , k = d i s t j , i + d i s t i , k 且 n u m j , k = n u m j , i ∗ n u m i , k dist_{j,k}=dist_{j,i}+dist_{i,k}且num_{j,k}=num_{j,i}*num_{i,k} distj,k=distj,i+disti,k且numj,k=numj,i∗numi,k
时间 O ( n 3 ) O(n^3) O(n3)
Code:
#include
#define maxn 210
#define LL long long
using namespace std;
int w[maxn][maxn], n, m;
LL num[maxn][maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main(){
n = read(), m = read();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) w[i][j] = 1e9;
for (int i = 1; i <= m; ++i){
int x = read(), y = read(), z = read();
w[x][y] = w[y][x] = min(w[x][y], z);
num[x][y] = num[y][x] = 1;
}
for (int k = 1; k <= n; ++k)
for (int i = 1; i <= n; ++i)
if (i != k)
for (int j = 1; j <= n; ++j)
if (i != j && j != k){
if (w[i][j] > w[i][k] + w[k][j]) w[i][j] = w[i][k] + w[k][j], num[i][j] = num[i][k] * num[k][j]; else
if (w[i][j] == w[i][k] + w[k][j]) num[i][j] += num[i][k] * num[k][j];
}
// printf("%d\n", num[1][3]);
int Flag = 0;
for (int i = 1; i <= n; ++i){
int flag = 0;
for (int j = 1; j <= n; ++j){
if (flag) break;
if (i != j)
for (int k = 1; k <= n; ++k)
if (i != k && j != k)
if (w[j][k] == w[j][i] + w[i][k] && num[j][k] == num[j][i] * num[i][k]){
printf("%d ", i);
flag = 1, Flag = 1;
break;
}
}
}
if (!Flag) puts("No important cities.");
return 0;
}