LA4080/UVa1416 Warfare And Logistics 最短路树
题目大意:
求图中两两点对最短距离之和
允许你删除一条边,让你最大化删除这个边之后的图中两两点对最短距离之和。
暴力:每次枚举删除哪条边,以每个点为源点做一次最短路,复杂度\(O(NM^2logN)\)。
值得注意的是,\(Dijkstra\)的复杂度\(O(NlogN)\)是关于边而非点的。
这个复杂度对于\(n=100,m=1000\)的数据难以接受。我们考虑对每个点建出其最短路树。容易想到,只有删除到这个点的最短路树上的边时,才需要再做一次\(Dijkstra\)。也就是说每个源点只需要做\(n\)次最短路,复杂度变成\(O(N^2MlogN)\)。
代码实现起来比较麻烦。。本弱调了整整一晚上。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 100 + 5;
const int M = 2000 + 5;
const int INF = 0x3f3f3f3f;
int n, m, l, kase, ban[M];
struct Graph {
int cnt, head[N];
struct Edge {int from, nxt, to, id, w;}e[M];
void clear () {
cnt = -1;
for (int i = 1; i <= n; ++i) {
head[i] = -1;
}
}
void add_edge (int u, int v, int w) {
++cnt; e[cnt] = (Edge) {u, head[u], v, cnt, w}; head[u] = cnt;
}
struct HeapNode {
int u; LL d;
bool operator < (HeapNode rhs) const {
return d > rhs.d;
}
};
priority_queue <HeapNode> pq;
int done[N], _fa[N][N]; LL _dis[N][N];
//dis[i][j] -> i to j
//fa[i][j] -> i as source, j's father
void dijkstra (int s) {
kase = kase + 1;
pq.push ((HeapNode) {s, 0});
LL *dis = _dis[s]; int *fa = _fa[s];
for (int i = 1; i <= n; ++i) {
fa[i] = -1, dis[i] = i == s ? 0 : INF;
}
while (!pq.empty ()) {
HeapNode now = pq.top (); pq.pop ();
if (done[now.u] == kase) continue;
for (int i = head[now.u]; ~i; i = e[i].nxt) {
int v = e[i].to;
if (ban[i]) continue;//禁用的边 -> 不用
if (dis[v] > dis[now.u] + e[i].w) {
fa[v] = now.u;
dis[v] = dis[now.u] + e[i].w;
pq.push ((HeapNode) {v, dis[v]});
}
}
done[now.u] = kase;
}
// cout << "s = " << s << endl;
// for (int i = 1; i <= n; ++i) {
// cout << "dis[" << i << "] = " << dis[i] << endl;
// }
}
}G;
bool have[N][M]; int minw[N][N];
struct Tree {
vector <int> Gr[N];
int sz[N]; LL sum[N], dis[N];
//sz[u] -> 点u的子树大小
//sum[u] -> 点u到其子树里所有点的距离和
void prep (int u) {
sz[u] = 1; sum[u] = dis[u];
for (int i = 0; i < (int)Gr[u].size (); ++i) {
int v = Gr[u][i];
prep (v);
sz[u] += sz[v];
sum[u] += sum[v];
}
}
void build (int s, LL *_dis, int *fa, int cmd) {
for (int i = 1; i <= n; ++i) Gr[i].clear ();
memcpy (dis, _dis, sizeof (dis));
for (int i = 1; i <= n; ++i) {
if (fa[i] != -1) {
Gr[fa[i]].push_back (i);
if (cmd == 1) {
have[fa[i]][i] = true;
have[i][fa[i]] = true;
}
}
}
prep (s);
// for (int i = 1; i <= n; ++i) {
// cout << "dis[" << i << "] = " << dis[i] << endl;
// cout << "sum[" << i << "] = " << sum[i] << endl;
// }
}
LL get_ans (int s, LL *_dis, int *fa, int cmd) {
build (s, _dis, fa, cmd);
return sum[s] + (n - sz[s]) * l;
}
}tr[N];//tr[i] -> 点i的最短路树
signed main () {
// freopen ("data.in", "r", stdin);
// freopen ("data.out", "w", stdout);
while (cin >> n >> m >> l) {
G.clear ();
memset (have, 0, sizeof (have));
memset (minw, 0x3f, sizeof (minw));
for (int i = 1; i <= m; ++i) {
static int u, v, w;
cin >> u >> v >> w;
G.add_edge (u, v, w);
G.add_edge (v, u, w);
minw[u][v] = min (minw[u][v], w);
minw[v][u] = min (minw[v][u], w);
}
LL ans1 = 0, ans2 = 0;
for (int s = 1; s <= n; ++s) {
G.dijkstra (s);
ans1 += tr[s].get_ans (s, G._dis[s], G._fa[s], 1);
//存一下最初的have
}
cout << ans1 << " ";
for (int i = 0; i <= G.cnt; i += 2) {
//每次枚举禁用一条边。
LL res_now = 0;
ban[i] = ban[i + 1] = true;//双向都要禁
for (int s = 1; s <= n; ++s) { //枚举删除之后每一棵最短路树的状况
int u = G.e[i].from, v = G.e[i].to, w = G.e[i].w;
if (have[u][v] && w == minw[u][v]) G.dijkstra (s);
res_now += tr[s].get_ans (s, G._dis[s], G._fa[s], 0);
}
ban[i] = ban[i + 1] = false;
ans2 = max (ans2, res_now);
}
cout << ans2 << endl;
}
}
LA4080/UVa1416 Warfare And Logistics 最短路树的更多相关文章
- UVA1416 Warfare And Logistics
UVA1416 Warfare And Logistics 链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36232 [ ...
- UVA1416/LA4080 Warfare And Logistics
题目大意:有N个点,M条路,如果两条路不连通的话,就将这两条路的距离设置为L 现在要求你求出每两点之间的最短距离和 接着要求 求出炸断 给出的M条路中的一条路后,每两点之间的最短距离和的最大值(翻译来 ...
- 【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条无向边的图,每条边权都为正.令 ...
- UVALive 4080 Warfare And Logistics (最短路树)
很多的边会被删掉,需要排除一些干扰进行优化. 和UVA - 1279 Asteroid Rangers类似,本题最关键的地方在于,对于一个单源的最短路径来说,如果最短路树上的边没有改变的话,那么最短路 ...
- la4080 Warfare And Logistics 罗列+最短
为了图.计算最短随机分ans1.和删除边缘.免费才能够获得最大和短路之间的最大分ans2,如果这两个不沟通.看作是两个点之间的最短距离l. 第一个想法是枚举每个边缘,然后运行n最短时间.但是,这种复杂 ...
- 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)
layout: post title: 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树) author: "luowentaoaa" ca ...
- Warfare And Logistics UVA - 1416
题目链接:https://vjudge.net/problem/UVA-1416 题解: 这是一个最短路的好题,首先我们考虑如果暴力弗洛伊德,显然时间复杂度不对,如果做n次spfa好像复杂度也不对,所 ...
- hdu 3409 最短路树+树形dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3409 参考博客:http://www.cnblogs.com/woaishizhan/p/318981 ...
- BZOJ1975[Sdoi2010]魔法猪学院——可持久化可并堆+最短路树
题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与 ...
随机推荐
- 服务器二:epoll
#include <unistd.h> #include <sys/types.h> #include <fcntl.h> #include <sys/soc ...
- OpenCL洗牌函数shuffle
在OpenCL中,经常会碰到会对向量的多个分量进行交叉运算的情况,比如 float4 d4; //input float scale; //input float2 mix_0 = mix((floa ...
- Parcelable 小记
Parcelable 类,接口类,用于数据的序列化封装.常见的Bundle,Intent类都实现了该类. 实现该类需要实现writeToParcel和describeContents方法,最后还需 ...
- 工具资源系列之给虚拟机装个windows
前面我们介绍了如何在 mac 宿主机安装 VMware 虚拟机软件,本节我们将继续介绍如何给虚拟机安装镜像,切换不同的操作系统. VMware 软件是容器,镜像是内核,这里的镜像指的是操作系统. 下载 ...
- 【Oracle教程资源大合集】Oracle数据库免费学习资源汇总
Oracle的产品非常丰富,各类学习资源也五花八门,本文将介绍Oracle官方的免费教程与风哥整理的Oracle视频教程: 1.Oracle帮助中心 Oracle帮助中心也称为Oracle文档中心,这 ...
- java连接sql server数据库(使用用户sa)
一.安装数据库相关软件 sql server management studio是管理sql server数据库的软件,想要使用需到微软官网下载安装sql server,然后再安装sql server ...
- 【原】无脑操作:IDEA热部署设置
热部署的概念:在应用正在运行的时候升级软件,却不需要重新启动应用.对于Java应用程序来说,热部署就是在运行时更新Java类文件. 注意:经过试验,IDEA 2017可以使用热部署,IDEA 14不行 ...
- iis问题
1.8.5版本的iis配置完成,不能打开网页显示503.原因是应用程序池,加载用户配置文件失败,然后应用程序池关闭了.关闭它就可以正常打开了. server2008,打不开网页,打开url显示目录的原 ...
- 第一次java作业
学习了c语言半个学期,好像刚开始并不担心Java,因为Java也是类同于C语言的一种语言,可是Java学到现在也将近一个月,在我脑子里现在却还没有一个框架,有点着急了.
- 一键发布部署vs插件[AntDeploy]开源了
deploy to remote server by one button click 功能 支持docker一键部署(支持netcore) 支持iis一键部署(支持netcore和framework ...