Warfare And Logistics UVA - 1416

题目链接: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\n",t[0],ans);
    }
    return 0;
}

 

posted @ 2017-09-09 11:04  人间失格—太宰治  阅读(270)  评论(0编辑  收藏  举报