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对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与 ...
随机推荐
- jsp内置对象-exception对象
1.概念:当JSP页面发生错误产生异常时,使用隐含对象exception针对该异常做出相应的处理.使用exception对象时,需要在page指令中设定:<%@page isErrorPage= ...
- mysql很有用的语句
1)删除表内所有数据: 再添加数据时,如果设有自动增加的id,那么id也会重置. truncate table 表名; 2)创建结构相同的数据库表 create table 数据库名.新表名 like ...
- datatable的部分问题处理(动态定义列头,给某行添加事件,初始显示空数据)
一.动态定义列头 在ajax中,用datatable再去重新配置列头,当然传回的数据中,要有对应放列头的键值对 我自定义了Mock数据,用于前端自己交互. 其中,rowdata用于存放传回的数据,co ...
- live-server 介绍&安装
live-server是可以运行前端静态文件的一个服务器,既然我们要前后端分离,所以就需要单独将html代码运行起来,这里我们选择live-server,等到后边真正部署的时候在用nginx js的解 ...
- SQLServer之数据库行锁
行锁使用注意事项 1.ROWLOCK行级锁确保在用户取得被更新的行,到该行进行更新,这段时间内不被其它用户所修改.因而行级锁即可保证数据的一致性,又能提高数据操作的并发性. 2.ROWLOCK告诉SQ ...
- zabbix监控交换机状态
1.在Zabbix中添加主机 输入名称.群组和交换机IP(交换机要开启snmp) 2.创建监控项 输入OID和其它信息(键值随便填,但是不能和系统内的键值重复)OID获取方法可查看上一篇文章:http ...
- Mysql5.6二进制包安装方法
1.Download MySQL Community Server 访问mysql官方网站转到下载页https://dev.mysql.com/downloads/mysql/5.6.html#dow ...
- Linux(CentOS7)yum安装卸载命令,离线下载安装包
一.Linux版本 二.yum安装 比如安装vim编辑器,y是自动应答,即默认一路确认,不用中途确认 yum install -y vim 三.yum卸载 比如卸载掉刚刚安装的vim yum eras ...
- 安装WebLogic失败,出现”[VALIDATION] [ERROR]:INST-07004: Oracle 主目录(O) 位置包含一个或多个无效字符“解决方案
题如图 解决方案: 在管理员cmd窗口定位到jdk bin目录,然后输入以下命令 java -jar F:\java\fmw_12.2.1.3.0_wls_quick_Disk1_1of1\fmw_1 ...
- css display和vertical-align 属性
display 定义和用法 display 属性规定元素应该生成的框的类型. 实例 <html> <head> <style type="text/css&qu ...