牛客算法周周练5 D 小雨坐地铁
题目
分析
这样的题目很容易想到 分层图 和 最短路, 而这类型的题目, 重点主要在建图上.
分层图中, 每一层自然是每一条地铁线路, 这个好说. 那层与层之间, 怎样建立关系呢?
可以这样理解吧, 将一个站台分成不同区域, 一个中转区, 多个(如果有的话)不同线路地铁的站台.
那么接下来就好说了.
从这个中转区到这一点其他站台, 都要交相应的车费 , 而从每个站台下车到中转区, 是不花钱的.
于是, 可以在额外的一层图中, 建立 n 个虚点, 即 n 个中转区, 连接该点所有的站台.
至此, 这个问题就解决了.
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <functional>
#include <utility>
using namespace std;
const int SIZE = 1e6;
const int INF = 0x3f3f3f3f;
struct Edge
{
    int end;
    int weight;
    int next;
};
Edge edge[SIZE];
int head[SIZE];
int edgestamp;
int dis[SIZE];
bool flag[SIZE];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > heap;
void addEdge(int u, int v, int w);
void dijkstra(int source);
int main()
{
    int n, m, s, t;
    int a, b, c;
    int u, v;
//    freopen("cpp.in", "r", stdin);
    scanf("%d %d %d %d", &n, &m, &s, &t);
    for (register int i = 1; i <= m; i++)
    {
        scanf("%d %d %d", &a, &b, &c);
        for (register int j = 1; j <= c; j++)
        {
            scanf("%d", &v);
            if (j > 1)
            {
                addEdge((i - 1) * n + u, (i - 1) * n + v, b);
                addEdge((i - 1) * n + v, (i - 1) * n + u, b);
            }
            addEdge((i - 1) * n + v, m * n + v, 0);
            addEdge(m * n + v, (i - 1) * n + v, a);
            u = v;
        }
    }
    dijkstra(m * n + s);
    if (dis[m * n + t] < INF)
        printf("%d\n", dis[m * n + t]);
    else
        printf("-1\n");
//    fclose(stdin);
    return 0;
}    
void addEdge(int u, int v, int w)
{
    edge[++edgestamp].end = v;
    edge[edgestamp].weight = w;
    edge[edgestamp].next = head[u];
    head[u] = edgestamp;
}
void dijkstra(int source)
{
    int u, v, w;
    memset(dis, 0x3f, sizeof(dis));
    memset(flag, false, sizeof(flag));
    dis[source] = 0;
    heap.push(make_pair(dis[source], source));
    while (!heap.empty())
    {
        u = heap.top().second;
        heap.pop();
        if (flag[u])
            continue;
        flag[u] = true;
        for (register int i = head[u]; i != 0; i = edge[i].next)
        {
            v = edge[i].end;
            w = edge[i].weight;
            if (dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                if (!flag[v])
                    heap.push(make_pair(dis[v], v));
            }
        }
    }
}
京公网安备 11010502036488号