• uva4080


    最短路树在本题的应用可以大大降低时间复杂度。

    题意求去掉一条边后所有点对的最短路径和c的最大值。

    常规思路是枚举边,对于每一条删掉的边,我们都求出此时的c,然后比较。

    但是这也意味着我们对于删掉的每条边都要做N次最短路,承受不起。

    我们发现,如果删掉的边不在当前起点的最短路树上,这删掉的边不会影响该起点对答案的贡献。(每个起点对答案的贡献是以它为起点的最短路径之和)

    所以我们只需要对于每一个起点,都求出它的最短路树,然后枚举边求解答案的时候判断一下该边在不在枚举起点的最短路树上即可。

    如果在,说明要重新算。如果不在,直接用第一次dijk算出的答案即可。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    const int maxn = 155, maxm = 2005, inf = 1e9;
    
    int n, m, l, tot;
    
    int h[maxn], w[maxn], dis[maxn], done[maxn], p[maxn][maxn], del[maxm];
    
    struct edge
    {
        int v, next, w, id;
    }a[maxm];
    
    struct edge2
    {
        int u, v, w;
    }e[maxm];
    
    struct node
    {
        int u, d;
        bool operator < (const node &rhs)const{
            return d > rhs.d;
        }
    };
    
    void add(int x, int y, int z, int id)
    {
        a[tot].id = id;
        a[tot].v = y;
        a[tot].w = z;
        a[tot].next = h[x];
        h[x] = tot++;
    }
    
    priority_queue<node> q;
    
    void dijk(int s)
    {
        for (int i = 1; i <= n; i++)
            dis[i] = inf;
        memset(done, 0, sizeof done);
        dis[s] = 0;
        q.push((node){s, 0});
        while (!q.empty())
        {
            node x = q.top(); q.pop();
            int u = x.u;
            if (done[u]) continue;
            done[u] = 1;
            for (int i = h[u]; ~i; i = a[i].next)
            {
                int v = a[i].v;
                if (dis[u] + a[i].w < dis[v])
                {
                    dis[v] = dis[u] + a[i].w;
                    p[s][v] = u;
                    q.push((node){v, dis[v]});
                }
            }
        }
        for (int i = 1; i <= n; i++)
            if (dis[i] == inf)
            {
                w[s] += l;
            }else
            {
                w[s] += dis[i];
            }
    }
    
    int dijk2(int s)
    {
        for (int i = 1; i <= n; i++)
            dis[i] = inf;
        memset(done, 0, sizeof done);
        dis[s] = 0;
        q.push((node){s, 0});
        while (!q.empty())
        {
            node x = q.top(); q.pop();
            int u = x.u;
            if (done[u]) continue;
            done[u] = 1;
            for (int i = h[u]; ~i; i = a[i].next)
            {
                if (del[a[i].id]) continue;
                int v = a[i].v;
                if (dis[u] + a[i].w < dis[v])
                {
                    dis[v] = dis[u] + a[i].w;
                    q.push((node){v, dis[v]});
                }
            }
        }
        int t = 0;
        for (int i = 1; i <= n; i++)
            if (dis[i] == inf)
                t += l;
            else t += dis[i];
        return t;
    }
    
    int main()
    {
    //    freopen("uva4080.in","r",stdin);
        while (~scanf("%d%d%d", &n, &m, &l))
        {
            memset(h, -1, sizeof h); tot = 0;
            for (int i = 1; i <= m; i++)
            {
                int x, y, z;
                scanf("%d%d%d", &x, &y, &z);
                e[i].u = x; e[i].v = y; e[i].w = z;
                add(x, y, z, i); add(y, x, z, i);
            }
            int ans1 = 0;
            for (int i = 1; i <= n; i++)
            {
                w[i] = 0;
                dijk(i);
                ans1 += w[i];
            }
            printf("%d ", ans1);
    //        for (int i = 1; i <= n; i++)//debug
    //        {
    //            printf("%d:%d
    ", i, w[i]);
    //        }
            int ans = 0;
            for (int i = 1; i <= m; i++)
            {
                del[i] = 1;
                int u = e[i].u, v = e[i].v;
                int t = 0;
                for (int s = 1; s <= n; s++)
                {
                    if(p[s][u] == v || p[s][v] == u)//在最短路树上
                        t += dijk2(s);
                    else t += w[s];
                }
                ans = max(ans, t);
                del[i] = 0;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    C++_标准模板库STL概念介绍2-泛型编程
    C++_标准模板库STL概念介绍1-建立感性认知
    C++_新特性1-类型转换运算符
    C++_新特性2-RTTI运行阶段类型识别
    C++_异常9-异常的注意事项
    C++_异常8-异常、类和基础
    C++_异常7-exception类
    C++_异常6-其他异常特性
    redis数据类型之—List
    redis数据类型之—Hash
  • 原文地址:https://www.cnblogs.com/yohanlong/p/7774231.html
Copyright © 2020-2023  润新知