• Warfare And Logistics UVA


    题目链接:https://vjudge.net/problem/UVA-1416

    题解:

      这是一个最短路的好题,首先我们考虑如果暴力弗洛伊德,显然时间复杂度不对,如果做n次spfa好像复杂度也不对,所以考虑优化这个暴力。

      我们考虑对于一个单源最短路,只有改变了最短路树中的某条边,才需要重新做一次最短路。所以我们不需要对于每条边都重新做最短路,只需要对于在最短路数上的边做,所以时间复杂度就优化成了你】

    mn^2log(n)。

      实现的时候要用pre数组记下,以i为终点的最短路树的边,实现有点复杂,看一下代码吧。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #define MAXN 10000
    #define ll long long
    using namespace std;
    struct edge{
        int first,next,to,quan,id;
    }a[MAXN*2];
    struct heapnode{
        int id,x;
        bool operator < (const heapnode &h)const{
            return h.x<x;
        }
    };
    priority_queue<heapnode> q;
    int dis[MAXN],have[MAXN],hh[MAXN],pre[MAXN],n,m,l,inf,num=0;
    ll t[MAXN];
    
    void addedge(int from,int to,int quan,int id){
        a[++num].to=to;
        a[num].id=id;
        a[num].quan=quan;
        a[num].next=a[from].first;
        a[from].first=num;
    }
    
    ll dij(int s,int cant){
        memset(dis,127,sizeof(dis));inf=dis[0];
        memset(have,0,sizeof(have));
        memset(pre,0,sizeof(pre));
        while(!q.empty()) q.pop();
        dis[s]=0;q.push((heapnode){s,0});
        while(!q.empty()){
            int now=q.top().id;
            q.pop();
            if(have[now]) continue;
            have[now]=1;
            for(int i=a[now].first;i;i=a[i].next){
                int to=a[i].to,quan=a[i].quan,id=a[i].id;
                if(id==cant) continue;
                if(dis[to]>dis[now]+quan){
                    pre[to]=id;
                    dis[to]=dis[now]+quan;
                    q.push((heapnode){to,dis[to]});
                }
            }
        }
        ll ret=0;
        for(int i=1;i<=n;i++){
            if(dis[i]==inf) ret+=l;
            else ret+=dis[i];
        }
        return ret;
    }
    
    void sovle(int s){
        int c=dij(s,0);
        for(int i=1;i<=n;i++) hh[i]=pre[i];
        for(int i=0;i<=m;i++) t[i]+=c;
        for(int i=1;i<=n;i++) if(hh[i]) t[hh[i]]+=dij(s,hh[i])-c;
    }
    
    int main()
    {
        while(scanf("%d%d%d",&n,&m,&l)!=EOF){
            memset(a,0,sizeof(a));
            memset(t,0,sizeof(t));
            num=0;
            for(int i=1;i<=m;i++){
                int x,y,z;scanf("%d%d%d",&x,&y,&z);
                addedge(x,y,z,i),addedge(y,x,z,i);
            }
            for(int i=1;i<=n;i++) sovle(i);
            ll ans=0;
            for(int i=1;i<=m;i++) ans=max(ans,t[i]);
            printf("%lld %lld
    ",t[0],ans);
        }
        return 0;
    }
  • 相关阅读:
    关于Windows版本的redis启动报错:Creating Server TCP listening socket 127.0.0.1:6379: bind: No error
    03 验证线程是数据共享的
    01 线程的两种创建方式
    33 线程的创建 验证线程之间数据共享 守护线程
    10 进程池的回调函数
    09 进程池的异步方法
    07 进程池的同步方法和异步方法
    08 进程池同步方法
    05 进程池map方法
    06 测试多进程的时间
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7497474.html
Copyright © 2020-2023  润新知