D 小雨坐地铁 最短路建图
题意:
思路:我们要建图,要考虑两个方面,一个是换线费用,一个是乘到下一站的费用
对于乘到下一站,这个很容易操作,就相邻的点按费用建边就可以
我们考虑这样操作:对于每一条线,都建出点来,即:每一条线上的同一个站点的代号是不一样的
举例如下:假如有n=5,m=5;
那么第一条线有1 2 3 4 5 这五个站点
第二条线有6 7 8 9 10 这五个站点
于是对于乘到下一站,这个很容易操作,就相邻的点按费用建边就可以
而换线,我们则是在一条线的某一个站点k,跑到另外一条线上的同一个站点k
于是我们需要一个总的点来包含这些被分开表示的点
如:用k+m*n 来包含(0~m-1+k 的点)
建边的时候,我们就是在总的点给当前点建费用边
在当前的点给总的点建0边
题目给出的n为1e3,m为500; (数据范围不大) 总的为n*m 可以接受
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=6e5+10; 4 const int inf=0x3f3f3f3f; 5 struct node 6 { 7 int v,w,nxt; 8 }G[maxn<<1]; 9 int n,m,s,t; 10 int head[maxn]; int num; 11 void add(int u,int v,int w) 12 { 13 G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num; 14 } 15 int vis[maxn]; 16 int dis[maxn]; 17 void SPFA(int x) 18 { 19 memset(dis,inf,sizeof(dis)); 20 memset(vis,0,sizeof(vis)); 21 queue<int>q; 22 q.push(x); 23 vis[x]=1; 24 dis[x]=0; 25 while(!q.empty()){ 26 //printf("1111111111111111\n"); 27 int u=q.front(); 28 q.pop(); 29 vis[u]=0; 30 for(int i=head[u];i;i=G[i].nxt){ 31 int v=G[i].v; 32 int w=G[i].w; 33 if(dis[v]>dis[u]+w){ 34 dis[v]=dis[u]+w; 35 if(!vis[v]){ 36 q.push(v); 37 vis[v]=1; 38 } 39 } 40 } 41 } 42 } 43 int main() 44 { 45 scanf("%d%d%d%d",&n,&m,&s,&t); 46 for(int i=1;i<=m;i++){ 47 int t1,t2,t3; 48 scanf("%d%d%d",&t1,&t2,&t3); 49 int u,v; 50 for(int k=1;k<=t3;k++){ 51 scanf("%d",&v); 52 if(k>1){ 53 add(u+(i-1)*n,v+(i-1)*n,t2); 54 add(v+(i-1)*n,u+(i-1)*n,t2); 55 } 56 add(v+(i-1)*n,v+m*n,0); 57 add(v+m*n,v+(i-1)*n,t1); 58 u=v; 59 } 60 } 61 SPFA(s+m*n); 62 if(dis[t+m*n]==inf) 63 printf("-1\n"); 64 else printf("%d\n",dis[t+m*n]); 65 return 0; 66 }