This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on.
The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
Help us calculate the shortest path from node 1 to node N.
For each test case, first line has three numbers N, M (0 <= N, M <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w. Output For test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
If there are no solutions, output -1. Sample Input
2 3 3 3 1 3 2 1 2 1 2 3 1 1 3 3 3 3 3 1 3 2 1 2 2 2 3 2 1 3 4Sample Output
Case #1: 2 Case #2: 3
分析:
本题的坑点在于建图的时候边数太多,因为每x层与x+1层中的每一个点都相互连接,这样就有 Nx^N(x+1) 条边,sum(Ni)为10^5,暴力建图肯定会爆的
建图的时候,每一层增加一个“层点”作为中介,然后层点与层点建边,层点与在该层上的点建边(边长为0),点与相邻层点建边(边长为c)。
最后增加的边,点与点建边。
在赛场上怂了,看见10^5没敢多建边,只想着如何在层之间建边了。。。对时间复杂度与时间限制的把握还是不好,以后要记住常用算法的复杂度,还要学习如何准确分析时间复杂度
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <vector> 6 #define maxn 200005 7 #define INF 0x3f3f3f3f 8 using namespace std; 9 10 int n,m,c,ans,cnt; 11 bool vis[maxn],vv[maxn]; 12 int dist[maxn],pp[maxn],lay[maxn]; 13 struct Node 14 { 15 int v,w; 16 int next; 17 } edge[20*maxn]; 18 queue<int>q; 19 20 void init() 21 { 22 memset(pp,0,sizeof(pp)); 23 memset(vv,0,sizeof(vv)); 24 memset(dist,0x3f,sizeof(dist)); 25 } 26 void addedge(int u,int v,int w) 27 { 28 cnt++; 29 edge[cnt].v=v; 30 edge[cnt].w=w; 31 edge[cnt].next=pp[u]; 32 pp[u]=cnt; 33 } 34 void SPFA() 35 { 36 int i,j,u,v,w; 37 memset(vis,0,sizeof(vis)); 38 while(!q.empty()) q.pop(); 39 dist[1]=0; 40 vis[1]=1; 41 q.push(1); 42 while(!q.empty()) 43 { 44 u=q.front(); 45 q.pop(); 46 vis[u]=0; 47 for(i=pp[u]; i; i=edge[i].next) 48 { 49 v=edge[i].v; 50 w=edge[i].w; 51 if(dist[v]>dist[u]+w) 52 { 53 dist[v]=dist[u]+w; 54 if(!vis[v]) 55 { 56 vis[v]=1; 57 q.push(v); 58 } 59 } 60 } 61 } 62 } 63 int main() 64 { 65 int i,j,t,u,v,w,test=0; 66 scanf("%d",&t); 67 while(t--) 68 { 69 scanf("%d%d%d",&n,&m,&c); 70 init(); 71 cnt=0; 72 for(i=1; i<=n; i++) 73 { 74 scanf("%d",&u); 75 lay[i]=u; 76 vv[u]=1; 77 } 78 for(i=1; i<n; i++) 79 { 80 if(vv[i]&&vv[i+1]) // 两层都出现过点相邻层才建边 81 { 82 addedge(n+i,n+i+1,c); 83 addedge(n+i+1,n+i,c); 84 } 85 } 86 for(i=1; i<=n; i++) // 层到点建边 点到相邻层建边 87 { 88 addedge(n+lay[i],i,0); 89 if(lay[i]>1) addedge(i,n+lay[i]-1,c); 90 if(lay[i]<n) addedge(i,n+lay[i]+1,c); 91 } 92 for(i=1; i<=m; i++) // 点到点建边 93 { 94 scanf("%d%d%d",&u,&v,&w); 95 addedge(u,v,w); 96 addedge(v,u,w); 97 } 98 SPFA(); 99 printf("Case #%d: ",++test); 100 ans=dist[n]; 101 if(ans<INF) printf("%d\n",ans); 102 else printf("-1\n"); 103 } 104 return 0; 105 }