试题 算法提高 文化之旅
资源限制
时间限制:1.0s 内存限制:128.0MB
问题描述
有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。不同的国家可能有相同的文化。不同文化的国家对其他文化的看法不同,有些文化会排斥外来文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。
现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求从起点到终点最少需走多少路。
输入格式
第一行为五个整数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)。
样例输入
2 2 1 1 2
1 2
0 1
1 0
1 2 10
样例输出
-1
输入输出样例说明
由于到国家2必须要经过国家1,而国家2的文明却排斥国家1的文明,所以不可能到达国家2。
样例输入
2 2 1 1 2
1 2
0 1
0 0
1 2 10
样例输出
10
输入输出样例说明
路线为1 -> 2。
数据规模和约定
对于20%的数据,有2≤N≤8,K≤5;
对于30%的数据,有2≤N≤10,K≤5;
对于50%的数据,有2≤N≤20,K≤8;
对于70%的数据,有2≤N≤100,K≤10;
对于100%的数据,有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。
解题思路:构图,有Dijkstra 算法找最短路 外加 可到达判定条件(“不同文化的国家对其他文化的看法不同,有些文化会排斥外来文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)”)。
AC代码如下:
#include <iostream>
#include <vector>
#include <string.h>
#include <queue>
using namespace std;
#define INF 65535
struct Way{
int from,to;
int val;
Way(int ff,int tt,int vv):from(ff),to(tt),val(vv){ }
Way(){ }
bool operator <(const Way &W) const{
return val>W.val;
}
};
int CTC[110];// 第i个国家的文化 为 CTC[i]
int cvis[110];// 文化i 是否可以被访问:0,可以;1,不可以。 也就是,之前已访问的文化是否排斥 文化i ,其实没用到
vector< vector<int> > Anti(110);// 文化i 排斥的文化 在 向量Anti[i]中
vector< vector<Way> > G(110);//图
int N,K,M,S,T;
int d[110];
vector<int> Learned;//已经学习的文化
void Read(){
cin>>N>>K>>M>>S>>T;
for(int i=1;i<=N;i++){
cin>>CTC[i]; //第i个数Ci,表示国家i的文化为Ci。
}
for(int i=1;i<=K;i++){
for(int j=1;j<=K;j++){
int a;
cin>>a;
if(a==1)
Anti[i].push_back(j);
}
}
for(int i=1;i<=M;i++){
int u,v,d;
cin>>u>>v>>d;
G[u].push_back(Way(u,v,d));
G[v].push_back(Way(v,u,d));
}
//初始化d
for(int i=1;i<=N;i++){
d[i]=INF;
}
}
bool isAnti(int SC){
for(int i=0;i<Anti[SC].size();i++){
int curA=Anti[SC][i];
for(int j=0;j<Learned.size();j++){
int lnd=Learned[j];
if(curA==lnd){
return true;
}
}
}
return false;
}
void Dijkstra(){
//memset(cvis,0,sizeof(cvis));
priority_queue<Way> PQ;
d[S]=0;
Learned.push_back(CTC[S]);
PQ.push(Way(S,S,d[S]));
while(!PQ.empty()){
int now=PQ.top().from;
PQ.pop();
for(int i=0;i<G[now].size();i++){
int to=G[now][i].to;
if(d[now]+G[now][i].val<d[to] && !isAnti(CTC[to]) ){
d[to]=d[now]+G[now][i].val;
Learned.push_back(CTC[to]);
PQ.push(Way(to,to,d[to]));
}
}
}
if(d[T]==INF)
cout<<"-1"<<endl;
else
cout<<d[T]<<endl;
}
int main(int argc, char** argv) {
Read();
Dijkstra();
return 0;
}