题目大意:有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)。。我不敢苟同

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
template<class T>
inline void swap(T &a, T &b)
{
T tmp = a;a = b;b = tmp;
}
inline void read(int &x)
{
x = ;char ch = getchar(), c = ch;
while(ch < '' || ch > '') c = ch, ch = getchar();
while(ch <= '' && ch >= '') x = x * + ch - '', ch = getchar();
if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = + ;
const int MAXM = + ;
struct Edge
{
int u,v,w,nxt;
Edge(int _u, int _v, int _w, int _nxt){u = _u, v = _v, w = _w, nxt = _nxt;}
Edge(){}
}edge[MAXM << ];
int head[MAXN], cnt = , d[MAXN][MAXN], dis[MAXM], flag, belong[MAXM][MAXN], vis[MAXN], p[MAXN][MAXN], l, tmp1, tmp2, tmp3, n, m;
//p[i]表示以i为起点的最短路树,在最短路树上,j的父亲的那条边
inline void insert(int a, int b, int c)
{
edge[++ cnt] = Edge(a,b,c,head[a]), head[a] = cnt;
}
struct Node
{
int u,w;
Node(int _u, int _w){u = _u, w = _w;}
Node(){}
};
struct cmp
{
bool operator()(Node a, Node b)
{
return a.w > b.w;
}
};
std::priority_queue<Node, std::vector<Node>, cmp> q;
void dij(int S, int *d, int size)
{
while(q.size())q.pop();memset(d, 0x3f, size), d[S] = , memset(vis, , sizeof(vis)), q.push(Node(S, ));
while(q.size())
{
Node now = q.top();q.pop();
if(vis[now.u]) continue; vis[now.u] = ;
for(int pos = head[now.u];pos;pos = edge[pos].nxt)
{
int v = edge[pos].v;
if(d[v] > d[now.u] + edge[pos].w)
{
d[v] = d[now.u] + edge[pos].w, q.push(Node(v, d[v]));
if(flag) p[S][v] = pos;
}
}
}
}
int main()
{
while(scanf("%d %d %d", &n, &m, &l) != EOF)
{
flag = , memset(head, , sizeof(head)), memset(belong, , sizeof(belong)), memset(p, , sizeof(p)), cnt = ;
for(int i = ;i <= m;++ i) read(tmp1), read(tmp2), read(tmp3), insert(tmp1, tmp2, tmp3), insert(tmp2, tmp1, tmp3);
for(int i = ;i <= n;++ i) dij(i, d[i], sizeof(d[i]));
long long ans1 = , ans2 = ans1, ans3 = ;
for(int i = ;i <= n;++ i)
for(int j = ;j <= n;++ j)
if(d[i][j] >= INF) ans1 += l;
else ans1 += d[i][j];
printf("%lld ", ans1);
flag = ans3 = ;
for(int i = ;i <= n;++ i)
for(int j = ;j <= n;++ j)
if(p[i][j]) belong[p[i][j]][i] = ;
for(int pos = ;pos <= cnt;pos += )
{
tmp1 = edge[pos].w;ans2 = ans1;
edge[pos].w = edge[pos ^ ].w = INF;
for(int S = ;S <= n;++ S)
if(belong[pos][S] || belong[pos^][S])
{
dij(S, dis, sizeof(dis));
for(int i = ;i <= n;++ i)
{
if(d[S][i] >= INF) ans2 -= l;
else ans2 -= d[S][i];
if(dis[i] >= INF) ans2 += l;
else ans2 += dis[i];
}
}
edge[pos].w = edge[pos ^ ].w = tmp1;
ans3 = max(ans3, ans2);
}
printf("%lld\n", ans3);
}
return ;
}

UVA1416/LA4080

最新文章

  1. JS数组求最大值和最小值
  2. java 获取实体类对象属性值的方法
  3. poj-2403-cup
  4. JavaSE学习总结第03天_Java基础语法2
  5. Microsoft Visual 的变态
  6. sass入门学习篇(一)
  7. ubuntu16.04安装eclipse后启动栏图标为问号
  8. Ubuntu 服务器设置软件多用户访问
  9. Android Studio中使用Git进行代码管理(分支、合并)
  10. 分享:五个非常有用的WP插件
  11. C# Dev XtraReport 简单测试
  12. Luogu P4197 Peaks
  13. Python重新安装pip
  14. oracle体系结构理解
  15. Html5与Css3知识点拾遗(七)
  16. 2845 ACM 豆子 beans
  17. 集群RedHat6.5+JDK1.8+Hadoop2.7.3+Spark2.1.1+zookeeper3.4.6+kafka2.11+flume1.6环境搭建步骤
  18. Linux 安装JavaEE环境之Tomcat安装笔记
  19. 知识picture
  20. BEGINNING SHAREPOINT&amp;#174; 2013 DEVELOPMENT 第14章节--使用Office Services开发应用程序 总结

热门文章

  1. 16.ajax_case05
  2. 2019 Multi-University Training Contest 6 Nonsense Time (纯暴力)
  3. 2019-8-31-dotnet-获取程序所在路径的方法
  4. ADS 下 flash 烧写程序原理及结构
  5. passwd的使用例子
  6. Python全栈开发:configparser模块
  7. 布局页中的特殊情况(比如说只有某页有的banner)
  8. 六. Default arguments 参数默认值
  9. Mac OS下使用ll等命令
  10. Mac系统下安装Vue-cli详细步骤