zoukankan      html  css  js  c++  java
  • AtCoder ARC061E Snuke's Subway Trip 最短路

    (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

    Catalog

    Problem:传送门

    Portal

     原题目描述在最下面。

    (n(1e5))个点, (m(2e5))条边, 每条边有一个属性值。经过一条同一属性值的连续路径花费为1。问从1到n的最小花费。


    Solution:

    我的解法

     直接边最短路搞,然后t的飞起。仔细一想,这样写的话有(2e5)个点,边数更是多到飞起,拿命跑啊,不过代码我还是放下面。


    正解:拆点

     把一条(u->v)属性为(c)的路径,拆成(u->uc, uc->vc, vc->v)三条路径,边权分别为(1, 0, 1)

     然后跑最裸的最短路就行,答案除(2)输出。

    why?

     为什么这样是对的呢?

     对于一个点连接的许多路径,从一条走向另一条,如果属性相同就不需要额外花费。这点怎么做到的呢?

     比如(x->y,y->z)属性均为(c):实际路径是(x->yc->z),经过了yc这个中间点,而且没有额外的花费。

     答案除(2)是因为出发和结束都算了一遍花费。


    AC_Code:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <queue>
    #include <unordered_map>
    #define fi first
    #define se second
    #define iis std::ios::sync_with_stdio(false)
    using namespace std;
    typedef long long LL;
    typedef unsigned long long uLL;
    typedef pair<int, int> pii;
    
    const int INF = 0x3f3f3f3f;
    const int MXN = 1e6 + 5;
    const int MXT = 2e7 + 6;
    const uLL base = 99959;
    
    unordered_map<uLL, int> mp;
    int n, m, tn;
    int head[MXN], tot;
    struct lp {
        int v, c, nex;
    }cw[MXT];
    int dis[MXT], vis[MXT], fa[MXN];
    void add_edge(int u,int v,int w) {
        cw[++tot].v = v;cw[tot].c = w;cw[tot].nex = head[u];
        head[u] = tot;
        cw[++tot].v = u;cw[tot].c = w;cw[tot].nex = head[v];
        head[v] = tot;
    }
    void dij() {
        priority_queue<pii,vector<pii>,greater<pii> >Q;
        for(int i = 1; i <= n; ++i) dis[i] = INF, vis[i] = 0;
        dis[1] = 0;
        Q.push({dis[1], 1});
        while(!Q.empty()) {
            pii now = Q.top();Q.pop();
            int u = now.se;
            if(vis[u]) continue;
            vis[u] = 1;
            for(int i = head[u]; ~i; i = cw[i].nex) {
                int v = cw[i].v;
                //if(vis[v]) continue;
                if(dis[v] > dis[u] + cw[i].c) {
                    dis[v] = dis[u] + cw[i].c;
                    Q.push({dis[v], v});
                }
            }
        }
        int ans = dis[tn];
        while(!Q.empty()) Q.pop();
        if(ans == INF) ans = -2;
        printf("%d
    ", ans/2);
    }
    int Fi(int x) {
        return fa[x] == x? x: fa[x] = Fi(fa[x]);
    }
    int get(int x, int y) {
        uLL tmp = x;
        tmp = tmp * base * base + y * base + x ^ y;
        if(mp[tmp]) return mp[tmp];
        mp[tmp] = ++n;
        return n;
    }
    int main(int argc, char const *argv[]) {
        while(~scanf("%d%d", &n, &m)) {
            memset(head, -1, sizeof(head));
            tot = -1;
            mp.clear();
            tn = n;
            for(int i = 1; i <= n; ++i) fa[i] = i;
            for(int i = 0, u, v, c, pa, pb, uc, vc; i < m; ++i) {
                scanf("%d%d%d", &u, &v, &c);
                pa = Fi(u), pb = Fi(v);
                fa[pa] = pb;
                uc = get(u, c); vc = get(v, c);
                add_edge(u,uc,1);add_edge(uc,vc,0);add_edge(vc,v,1);
                add_edge(v,vc,1);add_edge(vc,uc,0);add_edge(uc,u,1);
            }
            if(Fi(tn) != Fi(1)){
                printf("-1
    ");
                continue;
            }
            dij();
        }
        return 0;
    }
    

    TLE_code

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <queue>
    #include <unordered_map>
    #define fi first
    #define se second
    #define iis std::ios::sync_with_stdio(false)
    using namespace std;
    typedef long long LL;
    typedef unsigned long long uLL;
    typedef pair<int, int> pii;
    
    const int INF = 0x3f3f3f3f;
    const int MXN = 1e5 + 5;
    const int MXT = 4e5 + 6;
    
    int n, m;
    int head[MXN], tot;
    struct lp {
        int v, c, nex;
    }cw[MXT];
    vector<pii> mp[MXN];
    int dis[MXT], vis[MXT], fa[MXN];
    void add_edge(int u,int v,int w) {
        cw[++tot].v = v;cw[tot].c = w;cw[tot].nex = head[u];
        head[u] = tot;
        cw[++tot].v = u;cw[tot].c = w;cw[tot].nex = head[v];
        head[v] = tot;
    }
    void dij() {
        priority_queue<pii,vector<pii>,greater<pii> >Q;
        memset(dis, 0x3f, sizeof(dis));
        memset(vis, 0, sizeof(vis));
        for(int i = head[1]; ~i; i = cw[i].nex) {
            dis[i] = 1;
            Q.push({dis[i], i});
        }
        int ans = INF;
        while(!Q.empty()) {
            pii now = Q.top();Q.pop();
            if(vis[now.se]) continue;
            vis[now.se] = 1;
            int u = now.se, a = cw[u].v;
            if(a == n) {
                ans = min(ans, dis[u]);
                break;
            }
            for(int i = head[a]; ~i; i = cw[i].nex) {
                if(vis[i]) continue;
                if(dis[i]>dis[u]+(cw[i].c!=cw[u].c)) {
                    dis[i] = dis[u]+(cw[i].c!=cw[u].c);
                    Q.push({dis[i], i});
                }
            }
        }
        while(!Q.empty()) Q.pop();
        if(ans == INF) ans = -1;
        printf("%d
    ", ans);
    }
    int Fi(int x) {
        return fa[x] == x? x: fa[x] = Fi(fa[x]);
    }
    int main(int argc, char const *argv[]) {
        while(~scanf("%d%d", &n, &m)) {
            memset(head, -1, sizeof(head));
            tot = -1;
            for(int i = 1; i <= n; ++i) fa[i] = i;
            for(int i = 0, u, v, c, pa, pb; i < m; ++i) {
                scanf("%d%d%d", &u, &v, &c);
                add_edge(u, v, c);
                pa = Fi(u), pb = Fi(v);
                fa[pa] = pb;
            }
            if(Fi(n) != Fi(1)){
                printf("-1
    ");
                continue;
            }
            dij();
        }
        return 0;
    }
    

    Problem Description:

  • 相关阅读:
    hdu1565 用搜索代替枚举找可能状态或者轮廓线解(较优),参考poj2411
    cf1114D 区间dp基础
    poj2411 状态压缩-铺地板题型-轮廓线解法(最优)
    poj3254 炮兵阵地弱化版,记数类dp
    poj2441状态压缩dp基础
    zoj3471 状态压缩dp基础
    北极通讯网络(最小生成树)
    黑暗城堡(生成树)
    关押罪犯(并查集)
    搭配购买(并查集+0/1背包)
  • 原文地址:https://www.cnblogs.com/Cwolf9/p/9749976.html
Copyright © 2011-2022 走看看