zoukankan      html  css  js  c++  java
  • hdu 4725 The Shortest Path in Nya Graph 最短路 拆点

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4725

    十万个点 如果相邻层的点都各自建边的话 有可能就变成50000×50000条边 时间空间都爆了

    这里一个处理手法是 借鉴网络流的出点和入点的思想 把每一层抽象出一个出点和入点(注意不能让同层的点无代价互通)

    其中一种具体做法是

    把入点往该层的所有点连一条代价为0的单向边 把该层所有点往出点连一条代价为0的单向边

    把出点往相邻层的入点连一条代价为C的单向边

    其他的正常建边

    注意 入点不能连到同层的出点

    我用的是dijkstra + heap

    不过应该存在很多可以优化的地方

    网上也有不拆点的做法可以减少边数 但是每层抽象出一个或几个点的做法是没错的

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <set>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> P;
    
    const int maxv = 510000;
    const int maxe = 1000000;
    const int INF = 0x3fffffff;
    
    struct edge
    {
        int to, cost, next;
    }E[maxe];
    int head[maxv];
    int d[maxv];
    int si;
    
    priority_queue<P, vector<P>, greater<P> > que;
    
    void addedge(int u, int v, int cost)
    {
        E[si].to = v;
        E[si].cost = cost;
        E[si].next = head[u];
        head[u] = si++;
    }
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
    
        int T;
        scanf("%d", &T);
        int n, m, c, V;
        for(int t = 1; t <= T; t++)
        {
            memset(E, -1, sizeof(E));
            memset(head, -1, sizeof(head));
            si = 0;
    
            scanf("%d%d%d", &n, &m, &c);
            V = 3*n;
    
            for(int i = 1; i <= n; i++)
            {
                int layer;
                scanf("%d", &layer);
                addedge(i, n + 2*layer, 0);//out
                addedge(n + 2*layer - 1, i, 0);//in
            }
    
            for(int i = 1; i < n; i++)
            {
                addedge(n + 2*i, n + 2*(i+1) - 1, c);
                addedge(n + 2*(i+1), n + 2*i - 1, c);
            }
    
            for(int i = 0; i < m; i++)
            {
                int u, v, cost;
                scanf("%d%d%d", &u, &v, &cost);
                addedge(u, v, cost);
                addedge(v, u, cost);
            }
    
            fill(d, d + V + 10, INF);
            d[1] = 0;
            que.push(P(0, 1));
    
            while(!que.empty())
            {
                P p = que.top();
                que.pop();
                int v = p.second;
                if(d[v] < p.first)
                    continue;
                for(int i = head[v]; i != -1; i = E[i].next)
                {
                    edge e = E[i];
                    if(d[e.to] > d[v] + e.cost)
                    {
                        d[e.to] = d[v] + e.cost;
                        que.push(P(d[e.to], e.to));
                    }
                }
            }
    
            printf("Case #%d: ", t);
            if(d[n] == INF)
                printf("-1
    ");
            else
                printf("%d
    ", d[n]);
    
        }
        return 0;
    }
  • 相关阅读:
    家庭记账本1
    寒假福利5
    寒假福利4——定位功能
    寒假福利3——日期时间选择器
    寒假作业——家庭小账本1.6(总结)
    寒假作业——家庭小账本1.5
    寒假作业——家庭小账本1.4
    寒假作业——家庭小账本1.3
    寒假作业——家庭小账本1.2
    寒假作业——家庭小账本1.1
  • 原文地址:https://www.cnblogs.com/dishu/p/4314168.html
Copyright © 2011-2022 走看看