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 }
View Code

 

   

   

posted @ 2020-05-06 11:19  古比  阅读(124)  评论(0编辑  收藏  举报