小雨坐地铁【分层图】【最短路】

 

思路

  如果考虑暴力建图的方法

  对于每一条线路的每一个站点可到达的站点建边

  在每条线路有1e5个站点的条件下显然是不现实的

  如何解决建图的问题是此题的关键

  因为有转车和车费逐步增加的情况存在

  很容易想到分层图的概念

  通过把路线看作不同的图层

  就能把转车的概念转化为层与层之间的转化概念

  令图层层数为 0 ~ m

  其中第 m 层为中转线

  所有的转车行为必须先转入中转层,再改换到其他的路线层

  显然,去中转线的费用应为a[i],由中转层上其他车的费用为0

  之后对于每一层的路线只要正常建图即可

CODE

  1 #include <bits/stdc++.h>
  2 #define dbg(x) cout << #x << "=" << x << endl
  3 #define eps 1e-8
  4 #define pi acos(-1.0)
  5 
  6 using namespace std;
  7 typedef long long LL;
  8 
  9 template<class T>inline void read(T &res)
 10 {
 11     char c;T flag=1;
 12     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
 13     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
 14 }
 15 
 16 namespace _buff {
 17     const size_t BUFF = 1 << 19;
 18     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
 19     char getc() {
 20         if (ib == ie) {
 21             ib = ibuf;
 22             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
 23         }
 24         return ib == ie ? -1 : *ib++;
 25     }
 26 }
 27 
 28 int qread() {
 29     using namespace _buff;
 30     int ret = 0;
 31     bool pos = true;
 32     char c = getc();
 33     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
 34         assert(~c);
 35     }
 36     if (c == '-') {
 37         pos = false;
 38         c = getc();
 39     }
 40     for (; c >= '0' && c <= '9'; c = getc()) {
 41         ret = (ret << 3) + (ret << 1) + (c ^ 48);
 42     }
 43     return pos ? ret : -ret;
 44 }
 45 
 46 const int maxn = 2e6 + 7;
 47 const int inf  = 0x3f3f3f3f;
 48 
 49 int head[maxn << 1], edge[maxn << 1], w[maxn << 1], nxt[maxn << 1];
 50 int cnt;
 51 
 52 inline void BuildGraph (int u, int v, int c) {
 53     cnt++;
 54     edge[cnt] = v;
 55     nxt[cnt]  = head[u];
 56     w[cnt] = c;
 57     head[u] = cnt;
 58 }
 59 
 60 struct node {
 61     int u,v;
 62     bool operator <(const node &t) const {
 63         return u > t.u;
 64     }
 65 };
 66 
 67 int n,m,s,t,k;
 68 int dis[maxn << 1];
 69 bool vis[maxn << 1];
 70 
 71 priority_queue<node> q;
 72 
 73 void dijkstra(int s) {
 74     memset(dis, 0x3f, sizeof(dis));
 75     dis[s] = 0;
 76     node temp;
 77     temp.u = 0;
 78     temp.v = s;
 79     q.push(temp);
 80     while(!q.empty()) {
 81         int u = q.top().v;
 82         int d = q.top().u;
 83         q.pop();
 84         if(vis[u]) continue;
 85         vis[u] = true;
 86         for (int i = head[u]; i; i = nxt[i]) {
 87             int v = edge[i];
 88             int c = w[i];
 89             if(dis[v] > dis[u] + c && !vis[v]) {
 90                 dis[v] = dis[u] + c;
 91                 node p;
 92                 p.u = dis[v], p.v = v;
 93                 q.push(p);
 94             }
 95         }
 96     }
 97 }
 98 
 99 int a[maxn << 1], b[maxn << 1], c[maxn << 1];
100 
101 int main()
102 {
103     read(n); read(m); read(s); read(t);
104     for ( int i = 1; i <= m; ++i ) {
105         read(a[i]); read(b[i]); read(c[i]);
106         int u = 0, v = -1;
107         for ( int j = 1; j <= c[i]; ++j ) {
108             read(u);
109             if(~v) {
110                 BuildGraph((i - 1) * n + u, (i - 1) * n + v, b[i]);
111                 BuildGraph((i - 1) * n + v, (i - 1) * n + u, b[i]);
112             }
113             v = u;
114             BuildGraph((i - 1) * n + u, n * m + u, 0);
115             BuildGraph((n * m) + u, (i - 1) * n + u, a[i]);
116         }
117     }
118     dijkstra(n * m + s);
119     int ans = INT_MAX;
120     for ( int i = 1; i <= m; ++i ) {
121         ans = min(ans, dis[n * i + t]);
122     }
123     if(ans == inf) {
124         puts("-1");
125         return 0;
126     }
127     cout << ans << endl;
128     return 0;
129 }
View Code
原文地址:https://www.cnblogs.com/orangeko/p/12850336.html