Files
python/TangDou/CSP-J/AcWingTraining/T8/452.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

76 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
const int INF = 0x3f3f3f3f;
int n, K, m, S, T;
int c[N]; // 文化
int cg[N][N]; // 互斥关系
int g[N][N]; // 地图,不一定连通
int d[N][N]; // floyd用的多源最短路数组
int path[N], top; // 记录已经学过的文化
int ans = INF; // 答案
void dfs(int u, int dist) { // 从u出发,dist:已经走的步数
if (dist + d[S][u] >= ans) return; // 启发式剪枝,如果已经走的步数+从u到S的最短距离,已经大于目前的最小答案,那么,此路不通
if (u == S) { // 如果走到了S,收集答案
ans = dist;
return;
}
// 还没有走到起点,从哪个点走过来的
for (int i = 1; i <= n; i++) {
if (g[i][u] < INF) { // 可能从i点过来的
bool flag = true; // 文件上没有排斥
for (int j = 0; j < top; j++) { // 遍历一下所有已经走过的文化,是不是存在文化上的冲突
if (cg[path[j]][c[i]]) { // 如果i国家的文化,与后面已知国家的文化冲突,那么一定不是从i过去的
flag = false; // 不可能从i走到u
break;
}
}
if (flag) { // 文化上没有排斥
path[top++] = c[i]; // i号城市的文化c[i]进入数组
dfs(i, dist + g[i][u]); // 继续反向搜索
top--; // 回溯
}
}
}
}
int main() {
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
// 一般在数据量大于10W时考虑用scanf,如果scanf过不去,再考虑使用快读
cin >> n >> K >> m >> S >> T;
// 先读入文化
for (int i = 1; i <= n; i++) cin >> c[i];
for (int i = 1; i <= K; i++) // 读入排斥关系
for (int j = 1; j <= K; j++)
cin >> cg[i][j];
// 每个文化排斥自己
for (int i = 1; i <= K; i++) cg[i][i] = 1;
// 两个国家之间可能有多条道路,可能有重边
memset(g, 0x3f, sizeof g); // 任意两点间距离设置为正无穷,表示不连通
for (int i = 1; i <= n; i++) g[i][i] = 0; // 一开始每个国家都与自己连通
// 读入所有的边
while (m--) {
int a, b, c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b], c);
}
// Floyd 用于启发式剪枝,提前预处理出任意两点间的最短距离
memcpy(d, g, sizeof d);
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
path[top++] = c[T]; // 直播时忘记加入终点了,初始化终点
dfs(T, 0); // 从后往前搜索,玄学倒序,专克出题人
if (ans == INF) ans = -1; // 没有任何一个能走到S的,说明无解
cout << ans << endl;
return 0;
}