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