zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    MySQL客户端mysqladmin命令
    13 Linux磁盘管理
    12 Linux软件管理
    11 Linux压缩打包
    09 Linux输入输出
    08 LinuxACL控制
    07 Linux特殊权限
    06 Linux基本权限
    05 Linux用户管理
    04 Linux文件编辑
  • 原文地址:https://www.cnblogs.com/yohanlong/p/7774231.html
Copyright © 2011-2022 走看看