You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
3.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}