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;
}
时间: 2024-10-22 10:32:32

Warfare And Logistics UVA - 1416的相关文章

uva 1416 Warfare And Logistics (最短路树)

uva 1416 Warfare And Logistics Description The army of United Nations launched a new wave of air strikes on terrorist forces. The objective of the mission is to reduce enemy's logistical mobility. Each air strike will destroy a path and therefore inc

UVA - 1416 Warfare And Logistics (最短路)

Description The army of United Nations launched a new wave of air strikes on terroristforces. The objective of the mission is to reduce enemy's logistical mobility. Each airstrike will destroy a path and therefore increase the shipping cost of the sh

UVA 1416 - Warfare And Logistics(最短路树)

UVA 1416 - Warfare And Logistics 题目链接 题意:给定一个无向图,每个边一个正权,c等于两两点最短路长度之和,现在要求删除一边之后,新图的c值最大的是多少 思路:直接枚举删边,每次做一次dijkstra的话复杂度太高,其实如果建好最短路树,如果删去的边在最短路树上,才需要去做,这样复杂度就优化到(n^2mlog(n)),勉强可以接受 代码: #include <cstdio> #include <cstring> #include <vecto

UVA 1416 最短路树

Warfare And Logistics The army of United Nations launched a new wave of air strikes on terroristforces. The objective of the mission is to reduce enemy's logistical mobility. Each airstrike will destroy a path and therefore increase the shipping cost

Warfare And Logistics UVALive - 4080 (最短路树)

Warfare And Logistics UVALive - 4080 题意:给n个点m条边.令c为每对节点的最短路长度之和.要求删除一条边后使得新的c值c'最大,不连通的两点对短路视为L. [如果每次删除一条边,要跑m次dijkstra,其实其中很多次都对最短路没有影响,因为删掉的边不在最短路里] [因此,可以每次删除最短路树中的一条边,需要跑n次,复杂度降低到可接受程度] 1 #include <bits/stdc++.h> 2 #define LL long long 3 using

UVA 4080 Warfare And Logistics 战争与物流 (最短路树,变形)

题意:给一个无向图,n个点,m条边,可不连通,可重边,可多余边.两个问题,第一问:求任意点对之间最短距离之和.第二问:必须删除一条边,再求第一问,使得结果变得更大. 思路: 其实都是在求最短路的过程. 第一问可以floyd解决,也可以SSSP解决.注意是任意两个点,(a,b)和(b,a)是不同的,都要算. 第二问要穷举删除每条边,再求第一问.为了降低复杂度,假设用dijkstra求最短路,那么可以利用第一问中所生成的树,共n棵,每棵至多n-1条边,如果穷举的边不在该某树上,那么该树的所有路径长不

UVALive 4080 Warfare And Logistics

本题最关键的地方在于,对于一个单源的最短路径来说,如果最短路树上的边没有改变的话,那么最短路肯定是不会变的, 所以只要枚举删掉最短路树上的边.这样的时间复杂度就能过了. 瞎搞真删边,结果T了... #include<bits/stdc++.h> using namespace std; const int maxn = 102, maxm = 2002; int head[maxn], to[maxm], nxt[maxm],wei[maxm],ecnt; int delta[maxm]; v

la4080 Warfare And Logistics 罗列+最短

为了图.计算最短随机分ans1.和删除边缘.免费才能够获得最大和短路之间的最大分ans2,如果这两个不沟通.看作是两个点之间的最短距离l. 第一个想法是枚举每个边缘,然后运行n最短时间.但是,这种复杂性是1000*1000*100*log(100),太大了..事实上在固定起点,求出单元最短路的时候.同一时候能够求出单源最短路树,仅仅有删除的边在树上的时候.源点到任一点的最短路才会有变化,所以在每次跑单源最短路的时候,仅仅须要枚举树上的n-1条边就能够了.累加一下删除每一条边时,在当前源点的情况下

UVA1416 Warfare And Logistics

链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36232 [题意] 给出一个无向图,定义C =∑(d[i][j])  ,其中d[][]表示两点间的最短距离,求出C并求出删除一条边后的最大C2. [思路] 最短路树. 简单地想我们可以用SPFA求出每一个节点到另一个节点的最短距离,然后枚举删除m条边再次进行这项工作. 其实这里我们不用重新全部计算,因为如果所删除的边不在scr的最短路树上,那么这棵树不会被破坏.因此我们