UVA1416/LA4080 Warfare And Logistics

题目大意:有N个点,M条路,如果两条路不连通的话,就将这两条路的距离设置为L
现在要求你求出每两点之间的最短距离和
接着要求
求出炸断 给出的M条路中的一条路后,每两点之间的最短距离和的最大值(翻译来自http://blog.csdn.net/l123012013048/article/details/47297393)

单源最短路树:把源点到其他点的最短路拼起来,形成最短路树(可能有多棵,这里只需要一棵)。我们把起点为i的单源最短路树称为i源最短路树。想要让最短路改变,删除的边必定在这课最短路树上(但反过来不成立,即删除最短路树上的边最短路改变,是错误的)。处理出单源最短路树,然后用belong[i][j]表示边i是否在j源最短路树上,枚举边,重新做belong[i][j]为1的点即可。

这里仅仅是带来常数上的优化,实际复杂度并不能改变(nm^2logn),蓝书说复杂度变了(n^2mlogn)。。我不敢苟同

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <vector>
  8 #include <map>
  9 #include <string>
 10 #include <cmath>
 11 #define min(a, b) ((a) < (b) ? (a) : (b))
 12 #define max(a, b) ((a) > (b) ? (a) : (b))
 13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
 14 template<class T>
 15 inline void swap(T &a, T &b)
 16 {
 17     T tmp = a;a = b;b = tmp;
 18 }
 19 inline void read(int &x)
 20 {
 21     x = 0;char ch = getchar(), c = ch;
 22     while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar();
 23     while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar();
 24     if(c == ‘-‘) x = -x;
 25 }
 26 const int INF = 0x3f3f3f3f;
 27 const int MAXN = 200 + 10;
 28 const int MAXM = 2000 + 10;
 29 struct Edge
 30 {
 31     int u,v,w,nxt;
 32     Edge(int _u, int _v, int _w, int _nxt){u = _u, v = _v, w = _w, nxt = _nxt;}
 33     Edge(){}
 34 }edge[MAXM << 1];
 35 int head[MAXN], cnt = 1, d[MAXN][MAXN], dis[MAXM], flag, belong[MAXM][MAXN], vis[MAXN], p[MAXN][MAXN], l, tmp1, tmp2, tmp3, n, m;
 36 //p[i]表示以i为起点的最短路树,在最短路树上,j的父亲的那条边
 37 inline void insert(int a, int b, int c)
 38 {
 39     edge[++ cnt] = Edge(a,b,c,head[a]), head[a] = cnt;
 40 }
 41 struct Node
 42 {
 43     int u,w;
 44     Node(int _u, int _w){u = _u, w = _w;}
 45     Node(){}
 46 };
 47 struct cmp
 48 {
 49     bool operator()(Node a, Node b)
 50     {
 51         return a.w > b.w;
 52     }
 53 };
 54 std::priority_queue<Node, std::vector<Node>, cmp> q;
 55 void dij(int S, int *d, int size)
 56 {
 57     while(q.size())q.pop();memset(d, 0x3f, size), d[S] = 0, memset(vis, 0, sizeof(vis)), q.push(Node(S, 0));
 58     while(q.size())
 59     {
 60         Node now = q.top();q.pop();
 61         if(vis[now.u]) continue; vis[now.u] = 1;
 62         for(int pos = head[now.u];pos;pos = edge[pos].nxt)
 63         {
 64             int v = edge[pos].v;
 65             if(d[v] > d[now.u] + edge[pos].w)
 66             {
 67                 d[v] = d[now.u] + edge[pos].w, q.push(Node(v, d[v]));
 68                 if(flag) p[S][v] = pos;
 69             }
 70         }
 71     }
 72 }
 73 int main()
 74 {
 75     while(scanf("%d %d %d", &n, &m, &l) != EOF)
 76     {
 77         flag = 1, memset(head, 0, sizeof(head)), memset(belong, 0, sizeof(belong)), memset(p, 0, sizeof(p)), cnt = 1;
 78         for(int i = 1;i <= m;++ i) read(tmp1), read(tmp2), read(tmp3), insert(tmp1, tmp2, tmp3), insert(tmp2, tmp1, tmp3);
 79         for(int i = 1;i <= n;++ i) dij(i, d[i], sizeof(d[i]));
 80         long long ans1 = 0, ans2 = ans1, ans3 = 0;
 81         for(int i = 1;i <= n;++ i)
 82             for(int j = 1;j <= n;++ j)
 83                 if(d[i][j] >= INF) ans1 += l;
 84                 else ans1 += d[i][j];
 85         printf("%lld ", ans1);
 86         flag = ans3 = 0;
 87         for(int i = 1;i <= n;++ i)
 88             for(int j = 1;j <= n;++ j)
 89                 if(p[i][j]) belong[p[i][j]][i] = 1;
 90         for(int pos = 2;pos <= cnt;pos += 2)
 91         {
 92             tmp1 = edge[pos].w;ans2 = ans1;
 93             edge[pos].w = edge[pos ^ 1].w = INF;
 94             for(int S = 1;S <= n;++ S)
 95                 if(belong[pos][S] || belong[pos^1][S])
 96                 {
 97                     dij(S, dis, sizeof(dis));
 98                     for(int i = 1;i <= n;++ i)
 99                     {
100                         if(d[S][i] >= INF) ans2 -= l;
101                         else ans2 -= d[S][i];
102                         if(dis[i] >= INF) ans2 += l;
103                         else ans2 += dis[i];
104                     }
105                 }
106             edge[pos].w = edge[pos ^ 1].w = tmp1;
107             ans3 = max(ans3, ans2);
108         }
109         printf("%lld\n", ans3);
110     }
111     return 0;
112 }

UVA1416/LA4080

原文地址:https://www.cnblogs.com/huibixiaoxing/p/8397479.html

时间: 2024-10-13 05:29:32

UVA1416/LA4080 Warfare And Logistics的相关文章

【UVA1416】(LA4080) Warfare And Logistics (单源最短路)

题目: Sample Input4 6 10001 3 21 4 42 1 32 3 33 4 14 2 2Sample Output28 38 题意: 给出n个节点m条无向边的图,每条边权都为正.令c等于每对结点的最短路长度之和.要求删一条边后使得新的c值c‘最大.不连通两点的最短路长度视为L.(1<=n<=100,1<=m<=1000,1<=L<=10^8) 分析: 因为规模比较小,所以可以考虑删边.主要是删什么边的问题. 这里用到最短路树.在源点确定的情况下,只要

la4080 Warfare And Logistics 罗列+最短

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

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

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 1416 - Warfare And Logistics(最短路树)

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

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的最短路树上,那么这棵树不会被破坏.因此我们

Warfare And Logistics UVA - 1416

题目链接:https://vjudge.net/problem/UVA-1416 题解: 这是一个最短路的好题,首先我们考虑如果暴力弗洛伊德,显然时间复杂度不对,如果做n次spfa好像复杂度也不对,所以考虑优化这个暴力. 我们考虑对于一个单源最短路,只有改变了最短路树中的某条边,才需要重新做一次最短路.所以我们不需要对于每条边都重新做最短路,只需要对于在最短路数上的边做,所以时间复杂度就优化成了你] mn^2log(n). 实现的时候要用pre数组记下,以i为终点的最短路树的边,实现有点复杂,看

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