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对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与 ...
随机推荐
- 360浏览器兼容模式下IE内核版本
问题 最近在跟客户演示系统时,自己电脑IE 11下好好的,我们web系统最低支持到IE9.在客户电脑上,IE9浏览器下可以正常浏览,但是360兼容模式下,页面什么也不显示. 通过F12调试工具发现,3 ...
- 软件工程实践-WC项目之C实现
1.Github项目地址 https://github.com/ShadowEvan/homework 基本功能 -c 统计文件字符数(实现) -w 统计文件词数(实现) -l 统计文件行数(实现) ...
- 如何从GitHub下载csv文件
当打开存.csv文件的页面时,不用直接点击页面的Download,这样会使csv文件直接用浏览器打开. 要点击Raw按钮,鼠标右键,文件另存为,可以直接把csv文件下载到本地.
- 将对象xml序列化和反序列化
//将一个对象按XML序列化的方式写入到一个文件,使用的默认的UTF8编码格式 //o为要序列化的对象 //path保存文件的路径 public static object _lockObj=new ...
- 关于nginx unit服务非正常关闭后,无法重新启动问题的处理
昨天在前领导技术大牛吕哥的帮忙下,python服务管理从nginx+supervisor+uwsgi+python3改为了轻便结构nginx + unit + python3,部署和配置起来顿时轻松起 ...
- 【Teradata SQL】日历函数查询
查询2018年agmt_id=1076226890174464676612的,且金额类型代码为0212,每日协议金额. 1.协议金额历史表取某一日数据(20180101) sel t.start_dt ...
- 【spring源码分析】IOC容器初始化(八)
前言:在上文bean加载过程中还要一个非常重要的方法没有分析createBean,该方法非常重要,因此特意提出来单独分析. createBean方法定义在AbstractBeanFactory中: 该 ...
- 如何保持Redis和MySQL数据一致
原文:https://blog.csdn.net/thousa_ho/article/details/78900563 1. MySQL持久化数据,Redis只读数据 redis在启动之后,从数据库加 ...
- windows 和linux 路径解析的区别
windows下使用的是“\”作为分隔符,而linux则反其道而行之使用"/"作为分隔符.所以在windows 环境中获取路径常见 C:\windows\system 的形式,而l ...
- uWSGI、WSGI、uwsgi是什么?
uWSGI是一个web服务器,它实现了WSGI协议.uwsgi协议.HTTP等协议: WSGI是web服务器网管接口,是一套协议,用于接收用户请求并将请求进行初次封装,然后交给web框架: uwsgi ...