avatar
fireworks99
keep hungry keep foolish

HDU 4725 The shortest Path in Nya Graph

Description

N个点分别落在各层(layer), 每层可能有多个点, 也可能没有点, 每一层和其上下两层之间的点权值为C。另外有M条权值为w的边, 求1到N的最短路径, 如果不存在输出 -1

Analyze

如果N个点均匀落在相邻两层上,那么连线是N ^ 2级别的,会TLE

优化:每层设立一个层节点,(i + n)表示第i层的层节点标号

层节点指向本层所有节点,权值为0

本层所有节点指向相邻层的层节点,权值为w

before

after

上图例子中,优化前18条单向边,优化后12条

添加层节点消耗了空间,换取了时间

另外,Dijkstra堆优化真好用,用过即AC(好过stack实现的spfa)

还有,Dijkstra堆优化存图时用vector+pair

Code

#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 100105;
const int inf = 0x3f3f3f3f;

typedef pair<int, int> P;
vector<P> node[2 * N];

int layer[2 * N], head[2 * N], cnt, dis[2 * N], tot, sum, n, m, c;
bool vis[2 * N];

void init()
{
    cnt = 0;
    for(int i = 0; i <= n + n; ++i)
        dis[i] = inf, vis[i] = 0, node[i].clear(), layer[i] = 0;
}

void Dijkstra()
{
    priority_queue<P, vector<P>, greater<P> > q;
    dis[1] = 0;
    q.push(P(dis[1], 1));
    while(!q.empty())
    {
        P now = q.top();
        q.pop();
        int idx = now.second;
        if(vis[idx])
            continue;
        vis[idx] = 1;
        int sz = node[idx].size();
        for(int i = 0; i < sz; ++i)
        {
            P nxt = node[idx][i];
            if(dis[nxt.second] > dis[idx] + nxt.first)
            {
                dis[nxt.second] = dis[idx] + nxt.first;
                q.push(P(dis[nxt.second], nxt.second));
            }
        }
    }
}

int main()
{
    int t, tot = 1;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d%d", &n, &m, &c);
        init();
        for(int i = 1; i <= n; ++i)
            scanf("%d", &layer[i]);


        for(int i = 1; i <= n; ++i)///traverse each node instead of each layer
        {
            node[ layer[i] + n ].push_back(P(0, i));
            if(layer[i] > 1)
                node[i].push_back(P(c, layer[i] + n - 1));
            if(layer[i] < n)
                node[i].push_back(P(c, layer[i] + n + 1));
        }

        int u, v, w;
        for(int i = 1; i <= m; ++i)
        {
            scanf("%d %d %d", &u, &v, &w);
            node[u].push_back(P(w, v));
            node[v].push_back(P(w, u));
        }
        cout << "Case #" << tot++ << ": ";
        Dijkstra();
        if(dis[n] != inf)
            cout << dis[n] << '\n';
        else
            cout << "-1" << '\n';
    }
    return 0;
}
Site by Baole Zhao | Powered by Hexo | theme PreciousJoy