【题解】LuoGu1841:[JSOI2007]重要的城市

原题传送门
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 jk最短路非走不可的城市的充要条件是 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,knumj,k=numj,inumi,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;
}

你可能感兴趣的:(题解,LuoGu,最短路,题解,LuoGu,最短路)