1316 文化之旅
2012年NOIP全國聯賽普及組
有一位使者要遊歷各國,他每到一個國家,都能學到一種文化,但他不願意學習任何一種文化超過一次(即如果他學習了某種文化,則他就不能到達其他有這種文化的國家)。不同的國家可能有相同的文化。不同文化的國家對其他文化的看法不同,有些文化會排斥外來文化(即如果他學習了某種文化,則他不能到達排斥這種文化的其他國家)。
現給定各個國家間的地理關係,各個國家的文化,每種文化對其他文化的看法,以及這位使者遊歷的起點和終點(在起點和終點也會學習當地的文化),國家間的道路距離,試求從起點到終點最少需走多少路。
第一行為五個整數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)。
輸入樣例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
輸出樣例1
-1
輸出樣例2
10
【輸入輸出樣例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 }