【最短路】道路重建 @upcexam5797
时间限制: 1 Sec 内存限制: 128 MB 题目描述
小L的家乡最近遭遇了一场洪水,城市变得面目全非,道路也都被冲毁了。生活还要继续,于是市政府决定重建城市中的道路。
在洪水到来前,城市中共有n个区域和m条连接这些区域的双向道路, 道路连通了所有的区域,为了方便人们的出行,只能重建这些原有的道路,
不能建新的道路。编号为s的区域是市政广场,市政府希望重建的道路能够 使得所有区域到市政广场的最短路与受灾前保持不变,同时为了节约救灾
经费,还要使得修建的所有道路的长度和尽可能小。 小L为了拯救心爱的家乡,决定站出来,成为优秀的青年理论计算机科
学家,于是马上投入到了对这个问题的研究中。你能帮帮小L吗?输入
第一行两个整数n和m,表示区域与道路的个数。
接下来m行,每行三个正整数u,v和w,描述一条连接u和v、长为w的道路。 最后一行,一个正整数s,表示市政广场的编号。输出
输出一个整数,表示最小长度和。 样例输入 5 7 1 2 1 2 3 4 2 4 2 4 3 2 5 2 2 4 5 1 5 1 1
2 样例输出 6 提示 最优方案是重建1-2,1-5,2-4,4-3的道路,此时所有区域到达区域2的最短路分别是1, 0, 4, 2,
2,道路长度和是1 + 1 + 2 + 2 = 6。 对于20%的数据,n ≤ 10, m ≤ 20; 对于另外30%的数据,边权不超过2;
对于100%的数据,1 ≤ n ≤ 105, n − 1 ≤ m ≤ 2 ∗ 105, 1 ≤ w ≤ 109。来源 2018山东冬令营
先跑一遍Dijkstra,求出原点到每个点的最短路径长度d[i],
再一模一样跑一遍Dijkstra,只不过在每次更新操作时,维护每个点的最小入度值。
具体就是 如果dd[u](当前求得的原点到u的最短路长度)+e(u,v).w == d[v](第一次求得的最短路),
就维护d2[v] = min(d2[v],e(u,v).w);
#define FILE() freopen("../../in.txt","r",stdin)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//const int MOD = 1e9+7;
const int maxn = 100005,maxm = 200005;
const ll INF = 1e16+5;
int n,m,head[maxn],cnt;
ll d[maxn],dd[maxn],d2[maxn];
struct edge {
int v,nex;
ll w;
} ed[maxm*2];
struct node1{
int num,len;
};
struct node2{
int num,len;
};
bool operator < (node1 a,node1 b){
return d[a.num]>d[b.num];
}
bool operator < (node2 a,node2 b){
return dd[a.num]>dd[b.num];
}
priority_queue <node1> q;
priority_queue <node2> qq;
void addedge(int _u,int _v,ll _w) {
cnt++;
ed[cnt].v = _v;
ed[cnt].w = _w;
ed[cnt].nex = head[_u];
head[_u] = cnt;
}
void dij1(int start) {
for(int i=1;i<=n;i++)d[i] = INF;
d[start] = 0;
while(!q.empty())q.pop();
q.push((node1){start,0});
while(!q.empty()) {
int cur = q.top().num,len = q.top().len;
q.pop();
if(d[cur]<len)continue;
for(int i=head[cur]; i; i=ed[i].nex) {
int v=ed[i].v;
if(d[v]>d[cur]+ed[i].w){
d[v] = d[cur]+ed[i].w;
q.push((node1){v,d[v]});
}
}
}
}
void dij2(int start){
for(int i=1;i<=n;i++)dd[i] = d2[i] = INF;
dd[start] = d2[start] = 0;
while(!qq.empty())qq.pop();
qq.push((node2){start,0});
while(!qq.empty()) {
int cur = qq.top().num,len = qq.top().len;
qq.pop();
if(dd[cur]<len)continue;
for(int i = head[cur];i;i=ed[i].nex){
int v=ed[i].v;
if(dd[v]>dd[cur]+ed[i].w){
dd[v] = dd[cur]+ed[i].w;
qq.push((node2){v,dd[v]});
}
if(d[v]==dd[cur]+ed[i].w){
d2[v] = min(d2[v],ed[i].w);
}
}
}
}
int main() {
// FILE();
// freopen("../../out.txt","w",stdout);
cin>>n>>m;
for(int i=0; i<m; i++) {
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
int s;
cin>>s;
dij1(s);
dij2(s);
ll sum = 0;
for(int i=1;i<=n;i++)sum+=d2[i];
cout<<sum<<endl;
return 0;
}
【最短路】道路重建 @upcexam5797的更多相关文章
- 洛谷 P3905 道路重建 题解
P3905 道路重建 题目描述 从前,在一个王国中,在\(n\)个城市间有\(m\)条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有\(d\)条道路被破坏了.国王想 ...
- P1359 租用游艇 && P3905 道路重建 ------Floyd算法
P1359 租用游艇 原题链接https://www.luogu.org/problemnew/show/P1359 P3905 道路重建 原题链接https://www.luogu.org/ ...
- P3905 道路重建
P3905 道路重建我一开始想错了,我的是类似kruskal,把毁坏的边从小到大加,并且判断联通性.但是这有一个问题,你可能会多加,就是这条边没用,但是它比较小,你也加上了.居然还有10分,数据也是水 ...
- 洛谷——P3905 道路重建
P3905 道路重建 题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现 ...
- 洛谷 P3905 道路重建
题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...
- [JZOJ 5465] [NOIP2017提高A组冲刺11.9] 道路重建 解题报告 (e-dcc+树的直径)
题目链接: http://172.16.0.132/senior/#main/show/5465 题目: 小X所居住的X国共有n个城市,有m条无向道路将其连接.作为一个统一的国家,X 城的任意两个城市 ...
- 洛谷P3905 道路重建
题目:https://www.luogu.org/problemnew/show/P3905 分析: 此题是显然的最短路算法,只是看到一起删掉的一堆边感到十分棘手,而且还要求出的是最短添加边的总长度 ...
- SPFA--P3905 道路重建
题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...
- 【洛谷P1272】道路重建
题目大意:给定一个 N 个节点的树,求至少剪掉多少条边才能使得从树中分离出一个大小为 M 的子树. 题解:考虑树形 dp,定义 \(dp[u][i][t]\) 为以 u 为根节点与前 i 个子节点构成 ...
随机推荐
- Java 中 static 和 volatile 关键字的区别?
static指的是类的静态成员,实例间共享 volatile跟Java的内存模型有关,线程执行时会将变量从主内存加载到线程工作内存,建立一个副本,在某个时刻写回.valatile指的每次都读取主内存的 ...
- 【BZOJ】3730: 震波
原题链接 题解 查询距离一个点距离在一定范围内的点,直接点分树,前缀和用树状数组维护 答案是当前重心距离不超过k - (x到重心距离)的点的前缀和,减去在x所在子树中,距离重心不超过k - (x到重心 ...
- python全栈开发day80--评论楼、评论树
内容总结: 1. 内容回顾 1. 内容回顾 1.评论 1. 展示评论 1. 评论楼(Django模板语言渲染) 1. 从后端查询出所有的评论 2. 如果有父评论就展示父评论 2. 评论树 通过ajax ...
- 通过impala更改Kudu表属性
开发人员可以通过更改表的属性来更改 Impala 与给定 Kudu 表相关的元数据.这些属性包括表名, Kudu 主地址列表,以及表是否由 Impala (内部)或外部管理. Rename an Im ...
- tomcat 反代配置
tomcat反代可以基于nginx , http进行反代 反代服务器: 有两个网口 反代服务器一般有两块网卡一块处于外网,一块处于内网用于与后端服务器通信 tomcat 节点处于内网地址 1 tom ...
- POJ1459 Power Network 网络流 最大流
原文链接http://www.cnblogs.com/zhouzhendong/p/8326021.html 题目传送门 - POJ1459 题意概括 多组数据. 对于每一组数据,首先一个数n,表示有 ...
- JavaSE| String常用方法
字符串 * java.lang.String类型:字符串类型 * 1.String类型是final修饰,不能被继承的 * 2.Java 程序中的所有字符串字面值(如 "abc" ) ...
- 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组
题目描述: 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明:初始化 nums1 和 nums2 的元素数量分别为 m ...
- C++实现--最大公因数和最小公倍数
一丶 最大公因数求法: 辗转相除法(也称欧几里得算法)原理: 二丶最小公倍数求法:两个整数的最小公倍数等于两整数之积除以最大公约数 C++ 代码实现 #include <iostream ...
- js(javaScript)的各种事件触发,以常见为主eg:onclick
js的各种事件触发,以常见为主eg:onclick1.onclick,点击后触发事件 (1)<h1 onclick="this.innerHTML='谢谢!'">请点击 ...