1316 文化之旅 2012年NOIP全国联赛普及组

时间:2022-12-17 07:29:55
 
题目描述 Description

有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家)。不同的国家可能有相同的文化。不同文化的国家对其他文化的看法不同,有些文化会排斥外来文化(即如果他学习了某种文化,则他不能到达排斥这种文化的其他国家)。

现给定各个国家间的地理关系,各个国家的文化,每种文化对其他文化的看法,以及这位使者游历的起点和终点(在起点和终点也会学习当地的文化),国家间的道路距离,试求从起点到终点最少需走多少路。

输入描述 Input Description

第一行为五个整数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,两个国家之间可能有多条道路)。

输出描述 Output Description

输出只有一行,一个整数,表示使者从起点国家到达终点国家最少需要走的距离数(如果无解则输出-1)。

样例输入 Sample Input

输入样例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

 

样例输出 Sample Output

输出样例1

-1

 

输出样例2

10

 

数据范围及提示 Data Size & Hint

【输入输出样例1说明】

由于到国家2必须要经过国家1,而国家2的文明却排斥国家1的文明,所以不可能到达国家2。

【输入输出样例2说明】

路线为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≤N2,1≤ki≤K,1≤u,v≤N,1≤d≤1000,S≠T,1 ≤S, T≤N。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<queue>
  4 #include<cstring>
  5 using namespace std;
  6 const int maxn=0x7fffffff;
  7 struct node{
  8     int u,v,next,w;
  9 }edge[100001];
 10 
 11 
 12 int head[10001],num=1;
 13 int N,K,M,S,T;
 14  int flag[1000];
 15 
 16 
 17 void add_edge(int x,int y,int z)
 18 {
 19     edge[num].u=x;
 20     edge[num].v=y;
 21     edge[num].w=z;
 22     edge[num].next=head[x];
 23     head[x]=num++;
 24 }
 25 
 26 bool hate[1001][1001];int country[10001];
 27 int dis[10001],cul[10001];
 28 
 29 bool vis[10001];
 30 
 31 void spfa(int s)
 32 {
 33     queue<int>q;
 34     dis[s]=0;
 35     vis[s]=1;
 36     q.push(s);
 37     flag[s]--;
 38     while(q.size()!=0)
 39     {
 40         int p=q.front();
 41         q.pop();
 42         vis[p]=1;
 43         for(int i=head[p];i!=-1;i=edge[i].next)
 44         {
 45             int to=edge[i].v;
 46             if(dis[to]>dis[p]+edge[i].w&&flag[edge[i].v])
 47             {
 48                 flag[edge[i].v]--;
 49                 dis[to]=dis[p]+edge[i].w;
 50                 if(vis[to]==0)
 51                 {
 52                     q.push(to);
 53                     vis[to]=1;
 54                 }
 55             }
 56         }
 57             
 58     }
 59     if(dis[T]>=900)
 60     printf("-1");
 61     else 
 62     printf("%d",dis[T]);
 63 }
 64 int main()
 65 {
 66     memset(head,-1,sizeof(head));
 67     memset(dis,0x7f,sizeof(dis));
 68     
 69     scanf("%d%d%d%d%d",&N,&K,&M,&S,&T);
 70     for(int i=1;i<=N+30;i++)
 71     dis[i]=maxn;
 72     for(int i=1;i<=N;i++)
 73     {
 74         dis[i]=maxn;
 75         scanf("%d",&country[i]);
 76         cul[country[i]]=i;
 77     }
 78     int a;
 79     for(int i=1;i<=K;i++)
 80     for(int j=1;j<=K;j++)
 81     {
 82         scanf("%d",&a);
 83         if(i==j&&a==1)
 84         {
 85             flag[i]=1;
 86         }
 87         else 
 88         {
 89             flag[i]=0x7fffffff;
 90              hate[cul[i]][cul[j]]=a;
 91         }
 92     }
 93     int u,v,d;
 94     for(int i=1;i<=M;i++)
 95     {
 96         scanf("%d%d%d",&u,&v,&d);
 97         if(!hate[v][u])
 98         add_edge(u,v,d);
 99         if(!hate[u][v])
100         add_edge(v,u,d);
101     }
102     spfa(S);
103     return 0;
104 }