最短路 csu1808 地铁

来源:互联网 发布:icmp 端口不可达 编辑:程序博客网 时间:2024/04/28 01:29

传送门:点击打开链接

题意:告诉你很多条地铁线路,问最短路。

思路:首先我们考虑到d[pre][u]表示,从pre到达u时的最短路。
这种做法正确性是显然的,问题是肯定会炸。但是看到u的pre不可能是所有节点。
这也暗示了拆点,如果一个点按照被连的边,拆成几个点,然后再跑最短路。
由于最多只有m条边,所以拆点以后也最多只有2m个点。

#include <map>#include <set>#include <cmath>#include <ctime>#include <stack>#include <queue>#include <cstdio>#include <cctype>#include <bitset>#include <string>#include <vector>#include <cstring>#include <iostream>#include <algorithm>#include <functional>#define fuck(x) cout<<"["<<x<<"]";#define FIN freopen("input.txt","r",stdin);#define FOUT freopen("output.txt","w+",stdout);//#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef long long LL;typedef pair<int, int>PII; const int MX = 3e5 + 5;const int MS = 1e6 + 5;const LL INF = 0x3f3f3f3f3f3f3f3f; struct Edge {    int vstop, w, nxt;} E[MS];struct Stop {    int u, line;} S[MX];int Head[MX], erear;void edge_init() {    erear = 0;    memset(Head, -1, sizeof(Head));}void edge_add(int u, int v, int w) {    E[erear].w = w;    E[erear].vstop = v;    E[erear].nxt = Head[u];    Head[u] = erear++;} int n, m, osz;LL d[MX]; LL solve() {    LL ret = INF;    for(int i = 1; i <= osz; i++) d[i] = INF;    typedef pair<LL, int> Data;    priority_queue<Data, vector<Data>, greater<Data> > Q;    for(int i = Head[1]; ~i; i = E[i].nxt) {        int vid = E[i].vstop;        d[vid] = E[i].w;        Q.push(Data(d[vid], vid));    }    while(!Q.empty()) {        Data ftp = Q.top(); Q.pop();        if(d[ftp.second] != ftp.first) continue;         int uid = ftp.second, u = S[uid].u;        if(u == n) ret = min(ret, d[uid]);        for(int i = Head[u]; ~i; i = E[i].nxt) {            int vid = E[i].vstop;            LL cost = E[i].w + abs(S[uid].line - S[vid].line);            if(d[uid] + cost < d[vid]) {                d[vid] = d[uid] + cost;                Q.push(Data(d[vid], vid));            }        }    }    return ret;} int main() {    // FIN;    while(~scanf("%d%d", &n, &m)) {        osz = 0;        edge_init();        map<PII, int> order;         for(int i = 1; i <= m; i++) {            int u, v, line, w;            scanf("%d%d%d%d", &u, &v, &line, &w);            if(!order.count(PII(v, line))) {                order[PII(v, line)] = ++osz;                S[osz].u = v; S[osz].line = line;            }            edge_add(u, order[PII(v, line)], w);             if(!order.count(PII(u, line))) {                order[PII(u, line)] = ++osz;                S[osz].u = u; S[osz].line = line;            }            edge_add(v, order[PII(u, line)], w);        }        printf("%lld\n", solve());    }    return 0;}


1 0
原创粉丝点击