文化之旅

文化之旅 ⁡ \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 2N100

1 ≤ K ≤ 100 1≤K≤100 1K100

1 ≤ M ≤ N 2 1≤M≤N^2 1MN2

1 ≤ k i ≤ K 1≤k_i≤K 1kiK

1 ≤ u , v ≤ N 1≤u, v≤N 1u,vN

1 ≤ d ≤ 1000 , S ≠ T , 1 ≤ S , T ≤ N 1≤d≤1000,S≠T,1≤S,T≤N 1d1000,S=T,1S,TN

思路

这道题是一道最短路,我用 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值