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

题目:

Sample Input
4 6 1000
1 3 2
1 4 4
2 1 3
2 3 3
3 4 1
4 2 2
Sample Output
28 38

题意:

  给出n个节点m条无向边的图,每条边权都为正。令c等于每对结点的最短路长度之和。要求删一条边后使得新的c值c‘最大。不连通两点的最短路长度视为L。(1<=n<=100,1<=m<=1000,1<=L<=10^8)

分析:

  因为规模比较小,所以可以考虑删边。主要是删什么边的问题。

  这里用到最短路树。在源点确定的情况下,只要最短路树不被破坏,起点到所有点的距离都不会改变。所以对于一个点,只有删掉最短路树上的边,我们才要重新做一次单源最短路。时间复杂度是O(n^2mlogn)。

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 110
  9 #define Maxm 1100
 10 #define INF 100000000
 11
 12 struct node
 13 {
 14     int x,y,c,next;
 15     int ans;
 16     bool p;
 17 }t[Maxm*2];int len;
 18
 19 int first[Maxn],dis[Maxn];
 20 bool inq[Maxn];
 21 bool hp[Maxn];
 22 queue<int > q;
 23 int n,m,L;
 24
 25 void ins(int x,int y,int c)
 26 {
 27     t[++len].x=x;t[len].y=y;t[len].c=c;t[len].ans=0;
 28     t[len].next=first[x];first[x]=len;
 29 }
 30
 31 int mymax(int x,int y) {return x>y?x:y;}
 32
 33 void spfa(int s,int l)
 34 {
 35     if(!q.empty()) q.pop();
 36     memset(inq,0,sizeof(inq));
 37     memset(dis,63,sizeof(dis));
 38     memset(hp,0,sizeof(hp));
 39     q.push(s);dis[s]=0;hp[s]=1;inq[s]=1;
 40     while(!q.empty())
 41     {
 42         int x=q.front();inq[x]=0;q.pop();
 43         for(int i=first[x];i;i=t[i].next)
 44         {
 45             if(i==l) continue;
 46             if(i==(l%2==0?l-1:l+1)) continue;
 47             int y=t[i].y;hp[y]=1;
 48             if(dis[y]>dis[x]+t[i].c)
 49             {
 50                 dis[y]=dis[x]+t[i].c;
 51                 if(!inq[y])
 52                 {
 53                     q.push(y);
 54                     inq[y]=1;
 55                 }
 56             }
 57         }
 58     }
 59 }
 60
 61 int ffind(int s)
 62 {
 63     int now=0;
 64     for(int i=1;i<=n;i++) if(i!=s)
 65     {
 66         if(hp[i]) now+=dis[i];
 67         else now+=L;
 68     }
 69     return now;
 70 }
 71
 72 int main()
 73 {
 74     while(scanf("%d%d%d",&n,&m,&L)!=EOF)
 75     {
 76         memset(first,0,sizeof(first));
 77         len=0;
 78         for(int i=1;i<=m;i++)
 79         {
 80             int x,y,c;
 81             scanf("%d%d%d",&x,&y,&c);
 82             ins(x,y,c);ins(y,x,c);
 83         }
 84         int ft=0;
 85         for(int i=1;i<=n;i++)
 86         {
 87             spfa(i,0);int now=ffind(i);
 88             ft+=now;
 89             for(int j=1;j<=len;j++) t[j].p=0;
 90             for(int j=1;j<=len;j++)
 91             {
 92                 if(dis[t[j].x]==dis[t[j].y]+t[j].c) t[j].p=t[j%2==0?j-1:j+1].p=1;
 93             }
 94             for(int j=1;j<=len;j++)
 95             if(t[j].p)
 96             {
 97                 spfa(i,j);
 98                 t[j].ans+=ffind(i);
 99             }
100             else t[j].ans+=now;
101         }
102         int mx=ft;
103         for(int i=1;i<=len;i++) mx=mymax(mx,t[i].ans);
104         printf("%d %d\n",ft,mx);
105     }
106     return 0;
107 }

[UVA1416]

2016-04-05 14:04:01

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

【UVA1416】(LA4080) Warfare And Logistics (单源最短路)的相关文章

UVA1416/LA4080 Warfare And Logistics

题目大意:有N个点,M条路,如果两条路不连通的话,就将这两条路的距离设置为L 现在要求你求出每两点之间的最短距离和 接着要求 求出炸断 给出的M条路中的一条路后,每两点之间的最短距离和的最大值(翻译来自http://blog.csdn.net/l123012013048/article/details/47297393) 单源最短路树:把源点到其他点的最短路拼起来,形成最短路树(可能有多棵,这里只需要一棵).我们把起点为i的单源最短路树称为i源最短路树.想要让最短路改变,删除的边必定在这课最短路

la4080 Warfare And Logistics 罗列+最短

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

【算法系列学习】Dijkstra单源最短路 [kuangbin带你飞]专题四 最短路练习 A - Til the Cows Come Home

https://vjudge.net/contest/66569#problem/A http://blog.csdn.net/wangjian8006/article/details/7871889 邻接矩阵实现的单源最短路 1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 #include

Dijkstra算法 --- 单源最短路

Dijkstra算法适用于边权值为正的情况,可用于计算正权图上的单元最短路. 其伪代码如下: 设d[v0] = 0, 其他d[i] = INF 循环n次{ 在所有未标号的结点中,选取d值最小的结点x 给结点x加上永久标号 对于从x出发的所有边,执行松弛操作. } //松弛操作的伪代码如下: RELAX(u,v,w) if(u.d + w(u,v) < v.d){ v.d = w.d + w(u,v); pre[v] = u; } Dijkstra算法代码: /* Dijkstra 单源最短路算法

常见模板(欧拉筛素数,最小生成树,快排,并查集,单源最短路)

欧拉筛素数: #include<cstdio> #define maxn 10000000+10 using namespace std; int n,prime[5000001],num_prime=0,m; bool if_prime[maxn]; void euler(int limit) { for(int i=2;i<=limit;i++) { if(!if_prime[i]) prime[++num_prime]=i; for(int j=1;prime[j]*i<=l

利用分支限界法求解单源最短路(Dijkstra)问题

分支限界法定义:采用BFS算法,并使用剪枝函数的算法称为分支界限法. 分支限界法解释:按广度优先的原则,有选择的在其child中进行扩展,从而舍弃不含有最优解的分支,不断重复这一过程,直到找到答案或者判定无解. 分支界限法常常用到优先队列来选择最佳扩展节点,有时也会用到普通队列,以先进先出为原则来进行筛选. 单源最短路问题定义:给定有向图和起点,寻找到达所有点的最短路径. 单源最短路的分支限界法概述:首先把节点加入优先队列,之后不断地从队列中取出最优扩展点,观察其可抵达的所有目标节点,若当前路径

UVA 658 It&#39;s not a Bug, it&#39;s a Feature! (单源最短路,dijkstra+优先队列,变形,经典)

题意:有n个bug,有m个补丁,每个补丁有一定的要求(比如某个bug必须存在,某个必须不存在,某些无所谓等等),打完出来后bug还可能变多了呢.但是打补丁是需要时间的,每个补丁耗时不同,那么问题来了:要打多久才能无bug?(同1补丁可重复打) 分析: n<=20,那么用位来表示bug的话有220=100万多一点.不用建图了,图实在太大了,用位图又不好玩.那么直接用隐式图搜索(在任意点,只要满足转移条件,任何状态都能转). 但是有没有可能每个状态都要搜1次啊?那可能是100万*100万啊,这样出题

单源最短路_SPFA_C++

当我们需要求一个点到其它所有点的最短路时,我们可以采用SPFA算法 代码特别好写,而且可以有环,但是不能有负权环,时间复杂度是O(α(n)n),n为边数,α(n)为n的反阿克曼函数,一般小于等于4 模板:http://www.cnblogs.com/hadilo/p/5934679.html 我感觉自己讲的不会很好,丢一个链接算了 算法详解:http://www.360doc.com/content/13/1208/22/14357424_335569176.shtml 伪代码是自己写的: 可以

HDU-4849 Wow! Such City! (单源最短路)

Problem Description Doge, tired of being a popular image on internet, is considering moving to another city for a new way of life. In his country there are N (2 ≤N≤ 1000) cities labeled 0 . . . N - 1. He is currently in city 0. Meanwhile, for each pa