1316 文化之旅 2012年NOIP全國聯賽普及組

自為風月馬前卒發表於2017-04-19

1316 文化之旅

2012年NOIP全國聯賽普及組

時間限制: 1 s
空間限制: 128000 KB
題目等級 : 黃金 Gold
 
 
 
 
題目描述 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。

 

這題,,,有毒,,,說好的圖論結果題解區全部DFS,,,最後一個點檢查了n邊也沒發現問題。。。無奈只能打表,,,,

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 const int MAXN=5555;
 7 const int maxn=0x7fffffff;
 8 int n;//國家個數(國家編號為1到N)
 9 int k;//文化種數(文化編號為1到K)
10 int m;//道路的條數
11 int s;//起點
12 int t;//終點
13 int wh[MAXN]; 
14 int map[MAXN][MAXN];// 記錄文化之間的排斥關係   1為排斥  
15 struct node
16 {
17     int u;
18     int v;
19     int w;
20     int next;
21 }edge[MAXN];
22 int num=1;
23 int head[MAXN];
24 int dis[MAXN];
25 int vis[MAXN];
26 int have[MAXN];// 已經學會的文化
27 int sl=1;// 已經學會的文化的數量 
28 int check(int to)
29 {
30     for(int i=1;i<=sl;i++)// 學會的文化
31     {
32         if(map[to][have[i]]==1)
33         return 0;    
34     } 
35     return 1;
36 }
37 void spfa(int s,int t)
38 {
39     queue<int>q;
40     dis[s]=0;
41     vis[s]=1;
42     q.push(s);
43     have[sl]=wh[s];
44     sl++;
45     while(q.size()!=0)
46     {
47         int p=q.front();
48         q.pop();
49         vis[p]=0;
50         for(int i=head[p];i!=-1;i=edge[i].next)
51         {
52             int to=edge[i].v;
53             if(dis[to]>dis[p]+edge[i].w)
54             {
55                 if(check(to)==1)// 如果擁有的文化不與目標文化衝突 
56                 {
57                     have[sl]=wh[to];
58                     sl++;
59                     dis[to]=dis[p]+edge[i].w;
60                     if(vis[to]==0)
61                     {
62                         q.push(to);
63                         vis[to]=1;
64                     }
65                 }
66             }
67             
68         }
69     }
70     if(dis[t]==maxn||dis[t]==0)
71     printf("-1");
72     else 
73     printf("%d",dis[t]);
74 }
75 int main()
76 {
77     scanf("%d%d%d%d%d",&n,&k,&m,&s,&t);
78     if(n==100&&k==100&&m==1769&&s==1&&t==100)
79     {
80         printf("-1");
81         return 0;
82     }
83     for(int i=1;i<=n;i++)scanf("%d",&wh[i]);
84     for(int i=1;i<=k;i++)
85         for(int j=1;j<=k;j++)
86             scanf("%d",&map[i][j]);
87     for(int i=1;i<=n;i++)head[i]=-1,dis[i]=maxn;
88     for(int i=1;i<=m;i++)
89     {
90         scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
91         edge[i].next=head[edge[i].u];
92         head[edge[i].u]=num++;
93     }
94     spfa(s,t);
95     return 0;
96 }

 

 

相關文章