题目描述
有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一 种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。
不 同的国家可能有相同的文化。不同文化的国家对其他文化的看法不同,有些文化会排斥外来 文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。 现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这 位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求 从起点到终点最少需走多少路。
输入
第一行为五个整数 N,K,M,S,T,每两个整数之间用一个空格隔开,依次代表国家 个数(国家编号为 1 到 N),文化种数(文化编号为 1 到 K),道路的条数,以及起点和终点 的编号(保证 S 不等于 T); 第二行为 N 个整数,每两个整数之间用一个空格隔开,其中第 i 个数 Ci,表示国家 i 的文化为 Ci。 接下来的 K 行,每行 K 个整数,每两个整数之间用一个空格隔开,记第 i 行的第 j 个数 为 aij,aij= 1 表示文化 i 排斥外来文化 j(i 等于 j 时表示排斥相同文化的外来人),aij= 0 表示 不排斥(注意 i 排斥 j 并不保证 j 一定也排斥 i)。 接下来的 M 行,每行三个整数 u,v,d,每两个整数之间用一个空格隔开,表示国家 u 与国家 v 有一条距离为 d 的可双向通行的道路(保证 u 不等于 v,两个国家之间可能有多条 道路)。
输出
输出只有一行,一个整数,表示使者从起点国家到达终点国家最少需要走的距离数(如 果无解则输出-1)。
样例输入
【输入样例 1】
2 2 1 1 2
1 2
0 1
1 0
1 2 10
【输入样例 2】
2 2 1 1 2
1 2
0 1
0 0
1 2 10
样例输出
【输出样例 1】
-1
【输出样例 2】
10
提示
【输入输出样例1说明】
由于到国家 2 必须要经过国家 1,而国家 2 的文明却排斥国家 1 的文明,所以不可能到 达国家 2。
【输入输出样例2说明】
路线为 1 -> 2。
【数据范围】
有 2≤N≤100,1≤K≤100,1≤M≤N 2,1≤ki≤K,1≤u, v≤N,1≤d≤1000, S≠T,1 ≤S, T≤N。
这个题就是最短路径的问题,只不过加了一些约束条件,在用地杰斯特拉寻找最短路径的过程中,如果遇到某些国家的文化使者已经学习过,或者某些国家的文化排斥使者已经学过的文化,那么这些国家就直接pass,剩下的就是套地杰斯特拉板子
代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<string.h>
#include<math.h>
#include<queue>
using namespace std;
const int INF = 2e9+5;
const int mod = 1000007;
const int N = 105;
const int M = 10005;
bool vi[105];
struct Node {
int to;
int dis;
bool operator <(const Node &x)const {
return x.dis < dis;
}
};
priority_queue<Node> p;
int n, k, m, s, t;
int dis[N];
int head[N];
int ci[N];
int a[105];
bool aij[N][N];
struct Edge {
int to;
int dis;
int next;
}edge[M * 2];
int cnt = 0;
void add(int a, int b, int c) {
edge[++cnt].to = b;
edge[cnt].dis = c;
edge[cnt].next = head[a];
head[a] = cnt;
}
void dijkstra(int s) {
dis[s] = 0;
Node no;
no.to = s;
no.dis = 0;
p.push(no);
while (!p.empty()) {
Node node = p.top();
p.pop();
int cur = node.to;
vi[ci[cur]] = true;
for (int i = head[cur]; i != -1; i = edge[i].next) {
int to = edge[i].to;
int d = edge[i].dis;
bool flag = false;
for (int i = 1; i <= n; i++) {
if ((aij[ci[to]][i]&&vi[i])||vi[ci[to]]) {//约数条件,(aij[ci[to]][i]&&vi[i])代表要去的to国家的文化排斥使者已经学习过的文化vi【i】
//vi[ci[to]]代表要去的国家的文化ci【to】使者已经访问过
flag = true;
break;
}
}
if (flag)
continue;//如果要访问的点(国家)不满足条件,continue
if (dis[to] > dis[cur] + edge[i].dis) {
dis[to] = dis[cur] + edge[i].dis;
Node nod;
nod.dis = dis[to];
nod.to = to;
p.push(nod);
}
}
}
}
int main() {
memset(vi, false, sizeof(vi));//vi【i】代表文化i使者已经学习过,首先初始化false
memset(head, -1, sizeof(head));
cin >> n >> k >> m >> s >> t;
for (int i = 1; i <= n; i++) {
scanf("%d", &ci[i]);//ci【i】代表国家i的文化种类
}
int x;
for (int i = 1; i <= n; i++) {
dis[i] = INF;//将边初始化无穷
}
for (int i = 1; i <= k; i++) {
for (int j = 1; j <= k; j++) {
scanf("%d", &x);
if (x) {
aij[i][j] = true;//aij[i][j]代表i文化是否排斥j文化
}
else {
aij[i][j] = false;
}
}
}
int u, v, d;
for (int i = 1; i <= m; i++) {//邻接表存图
scanf("%d%d%d", &u, &v, &d);
add(u, v, d);
add(v, u, d);
}
dijkstra(s);
if (dis[t] == INF)
printf("-1");
else
printf("%d", dis[t]);
}