文化之旅 \operatorname{文化之旅} 文化之旅
题目链接: luogu P1078 \operatorname{luogu\ P1078} luogu P1078
题目背景
本题是错题,后来被证明没有靠谱的多项式复杂度的做法。测试数据非常的水,各种玄学做法都可以通过(比如反着扫),不代表算法正确。因此本题题目和数据仅供参考。
题目
有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。不同的国家可能有相同的文化。不同文化的国家对其他文化的看法不同,有些文化会排斥外来文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。
现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求从起点到终点最少需走多少路。
输入
第一行为五个整数 N , K , M , S , T N,K,M,S,T N,K,M,S,T ,每两个整数之间用一个空格隔开,依次代表国家个数(国家编号为 1 1 1 到 N N N ),文化种数(文化编号为 1 1 1 到 K K K ),道路的条数,以及起点和终点的编号(保证 S S S 不等于 T T T );
第二行为 N N N 个整数,每两个整数之间用一个空格隔开,其中第 i i i 个数 C i C_i Ci ,表示国家 i i i 的文化为 C i C_i Ci 。
接下来的 K K K 行,每行 K K K 个整数,每两个整数之间用一个空格隔开,记第 i i i 行的第 j j j 个数为 a i j a_{ij} aij , a i j = 1 a_{ij}= 1 aij=1 表示文化 i i i 排斥外来文化 j j j ( i i i 等于 j j j 时表示排斥相同文化的外来人), a i j = 0 a_{ij}= 0 aij=0 表示不排斥(注意 i i i 排斥 j j j 并不保证 j j j 一定也排斥 i i i )。
接下来的 M M M 行,每行三个整数 u , v , d u,v,d u,v,d ,每两个整数之间用一个空格隔开,表示国家 u u u 与国家 v v v 有一条距离为 d d d 的可双向通行的道路(保证 u u u 不等于 v v v ,两个国家之间可能有多条道路)。
输出
一个整数,表示使者从起点国家到达终点国家最少需要走的距离数(如果无解则输出 − 1 -1 −1 )。
样例输入1
2 2 1 1 2
1 2
0 1
1 0
1 2 10
样例输出1
-1
样例解释1
由于到国家 2 2 2 必须要经过国家 1 1 1 ,而国家 2 2 2 的文明却排斥国家 1 1 1 的文明,所以不可能到达国家 2 2 2 。
样例输入2
2 2 1 1 2
1 2
0 1
0 0
1 2 10
样例输出2
10
样例解释2
路线为 1 − > 2 1 -\!\!> 2 1−>2
数据范围
对于 100 % 100\% 100% 的数据,有 2 ≤ N ≤ 100 2≤N≤100 2≤N≤100
1 ≤ K ≤ 100 1≤K≤100 1≤K≤100
1 ≤ M ≤ N 2 1≤M≤N^2 1≤M≤N2
1 ≤ k i ≤ K 1≤k_i≤K 1≤ki≤K
1 ≤ u , v ≤ N 1≤u, v≤N 1≤u,v≤N
1 ≤ d ≤ 1000 , S ≠ T , 1 ≤ S , T ≤ N 1≤d≤1000,S≠T,1≤S,T≤N 1≤d≤1000,S=T,1≤S,T≤N
思路
这道题是一道最短路,我用 spfa 来做的。
用 dfs 来做 spfa ,而且排斥的国家就是不能到,还有记得同一个文明其实是排斥自己的,因为一个文明到了就不能再到。
就没什么了。
代码
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
struct node {
int x, to, nxt;
}e[20001];
int n, k, m, s, t, c[101], x, y, z, itunlike[101][101], le[10001], kk, gango[101], dis[101], cul[101][101], nxtone, last;
bool in[101];
void add() {
e[++kk] = (node){z, y, le[x]}; le[x] = kk;
e[++kk] = (node){z, x, le[y]}; le[y] = kk;
}
void spfa(int now) {
in[now] = 1;
for (int i = 1; i <= itunlike[now][0]; i++)
gango[itunlike[now][i]]++;
for (int i = le[now]; i; i = e[i].nxt)
if (!gango[e[i].to] && dis[e[i].to] > dis[now] + e[i].x) {
dis[e[i].to] = dis[now] + e[i].x;
if (!in[e[i].to])
spfa(e[i].to);
}
in[now] = 0;
for (int i = 1; i <= itunlike[now][0]; i++)
gango[itunlike[now][i]]--;
}
int main() {
memset(dis, 0x7f, sizeof(dis));//初始化
int ch = dis[0];
scanf("%d %d %d %d %d", &n, &k, &m, &s, &t);//读入
for (int i = 1; i <= n; i++) {
scanf("%d", &c[i]);
cul[c[i]][++cul[c[i]][0]] = i;//记录
}
for (int i = 1; i <= k; i++)
for (int j = 1; j <= k; j++) {
scanf("%d", &x);//读入
if (i == j) {//同一个文化的国家不能走了再走(等于排斥)
for (int K = 1; K <= cul[i][0]; K++)
for (int l = 1; l <= cul[j][0]; l++)
itunlike[cul[j][l]][++itunlike[cul[j][l]][0]] = cul[i][K];
continue;
}
if (!x) continue;
for (int K = 1; K <= cul[i][0]; K++)//排斥
for (int l = 1; l <= cul[j][0]; l++)
itunlike[cul[j][l]][++itunlike[cul[j][l]][0]] = cul[i][K];
}
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &x, &y, &z);//读入
add();//建图
}
dis[s] = 0;//初始化
spfa(s);//spfa最短路
if (dis[t] == ch) {//不能到
printf("-1");
return 0;
}
printf("%d", dis[t]);//输出
return 0;
}