时间限制: 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的更多相关文章

  1. 洛谷 P3905 道路重建 题解

    P3905 道路重建 题目描述 从前,在一个王国中,在\(n\)个城市间有\(m\)条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有\(d\)条道路被破坏了.国王想 ...

  2. P1359 租用游艇 && P3905 道路重建 ------Floyd算法

    P1359 租用游艇   原题链接https://www.luogu.org/problemnew/show/P1359 P3905 道路重建   原题链接https://www.luogu.org/ ...

  3. P3905 道路重建

    P3905 道路重建我一开始想错了,我的是类似kruskal,把毁坏的边从小到大加,并且判断联通性.但是这有一个问题,你可能会多加,就是这条边没用,但是它比较小,你也加上了.居然还有10分,数据也是水 ...

  4. 洛谷——P3905 道路重建

    P3905 道路重建 题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现 ...

  5. 洛谷 P3905 道路重建

    题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...

  6. [JZOJ 5465] [NOIP2017提高A组冲刺11.9] 道路重建 解题报告 (e-dcc+树的直径)

    题目链接: http://172.16.0.132/senior/#main/show/5465 题目: 小X所居住的X国共有n个城市,有m条无向道路将其连接.作为一个统一的国家,X 城的任意两个城市 ...

  7. 洛谷P3905 道路重建

    题目:https://www.luogu.org/problemnew/show/P3905 分析: 此题是显然的最短路算法,只是看到一起删掉的一堆边感到十分棘手,而且还要求出的是最短添加边的总长度 ...

  8. SPFA--P3905 道路重建

    题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...

  9. 【洛谷P1272】道路重建

    题目大意:给定一个 N 个节点的树,求至少剪掉多少条边才能使得从树中分离出一个大小为 M 的子树. 题解:考虑树形 dp,定义 \(dp[u][i][t]\) 为以 u 为根节点与前 i 个子节点构成 ...

随机推荐

  1. Java 中 static 和 volatile 关键字的区别?

    static指的是类的静态成员,实例间共享 volatile跟Java的内存模型有关,线程执行时会将变量从主内存加载到线程工作内存,建立一个副本,在某个时刻写回.valatile指的每次都读取主内存的 ...

  2. 【BZOJ】3730: 震波

    原题链接 题解 查询距离一个点距离在一定范围内的点,直接点分树,前缀和用树状数组维护 答案是当前重心距离不超过k - (x到重心距离)的点的前缀和,减去在x所在子树中,距离重心不超过k - (x到重心 ...

  3. python全栈开发day80--评论楼、评论树

    内容总结: 1. 内容回顾 1. 内容回顾 1.评论 1. 展示评论 1. 评论楼(Django模板语言渲染) 1. 从后端查询出所有的评论 2. 如果有父评论就展示父评论 2. 评论树 通过ajax ...

  4. 通过impala更改Kudu表属性

    开发人员可以通过更改表的属性来更改 Impala 与给定 Kudu 表相关的元数据.这些属性包括表名, Kudu 主地址列表,以及表是否由 Impala (内部)或外部管理. Rename an Im ...

  5. tomcat 反代配置

    tomcat反代可以基于nginx , http进行反代 反代服务器: 有两个网口  反代服务器一般有两块网卡一块处于外网,一块处于内网用于与后端服务器通信 tomcat 节点处于内网地址 1 tom ...

  6. POJ1459 Power Network 网络流 最大流

    原文链接http://www.cnblogs.com/zhouzhendong/p/8326021.html 题目传送门 - POJ1459 题意概括 多组数据. 对于每一组数据,首先一个数n,表示有 ...

  7. JavaSE| String常用方法

    字符串 * java.lang.String类型:字符串类型 * 1.String类型是final修饰,不能被继承的 * 2.Java 程序中的所有字符串字面值(如 "abc" ) ...

  8. 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组

    题目描述: 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明:初始化 nums1 和 nums2 的元素数量分别为 m ...

  9. C++实现--最大公因数和最小公倍数

    一丶 最大公因数求法: 辗转相除法(也称欧几里得算法)原理:   二丶最小公倍数求法:两个整数的最小公倍数等于两整数之积除以最大公约数   C++ 代码实现 #include <iostream ...

  10. js(javaScript)的各种事件触发,以常见为主eg:onclick

    js的各种事件触发,以常见为主eg:onclick1.onclick,点击后触发事件 (1)<h1 onclick="this.innerHTML='谢谢!'">请点击 ...