洛谷 P3905 道路重建 题解
P3905 道路重建
题目描述
从前,在一个王国中,在\(n\)个城市间有\(m\)条道路连接,而且任意两个城市之间至多有一条道路直接相连。在经过一次严重的战争之后,有\(d\)条道路被破坏了。国王想要修复国家的道路系统,现在有两个重要城市\(A\)和\(B\)之间的交通中断,国王希望尽快的恢复两个城市之间的连接。你的任务就是修复一些道路使\(A\)与\(B\)之间的连接恢复,并要求修复的道路长度最小。
输入格式
输入文件第一行为一个整数\(n(2<n≤100)\),表示城市的个数。这些城市编号从\(1\)到\(n\)。
第二行为一个整数\(m(n-1≤m≤\frac{1}{2} n(n-1))\),表示道路的数目。
接下来的\(m\)行,每行\(3\)个整数\(i,j,k(1≤i,j≤n,i≠j,0<k≤100)\),表示城市\(i\)与\(j\)之间有一条长为\(k\)的道路相连。
接下来一行为一个整数\(d(1≤d≤m)\),表示战后被破坏的道路的数目。在接下来的\(d\)行中,每行两个整数\(i\)和\(j\),表示城市\(i\)与\(j\)之间直接相连的道路被破坏。
最后一行为两个整数A和B,代表需要恢复交通的两个重要城市。
输出格式
输出文件仅一个整数,表示恢复\(A\)与\(B\)间的交通需要修复的道路总长度的最小值。
输入输出样例
输入 #1
3
2
1 2 1
2 3 2
1
1 2
1 3
输出 #1
1
【三种方法】
1.【最简单的弗洛伊德】
【思路】
弗洛伊德的方法
先将有路的点都连接起来
由于只需要修改损坏的点
所以完好的道路是可以走的而且不需要修复
所以消耗为0
可以把损坏的边标记一下
把没被标记的也就是完好的边改为0
因为不需要消耗
最后再跑一遍弗洛伊德就好了
【完整代码】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int Max = 102;
int f[Max][Max];
bool use[Max][Max];
int main()
{
int n,m,k;
int x,y,z;
scanf("%d%d",&n,&m);
for(register int i = 1;i <= n;++ i)
for(register int j = 1;j <= n;++ j)
f[i][j] = 999;
for(register int i = 1;i <= m;++ i)
{
cin >> x >> y >> z;
f[x][y] = f[y][x] = z;
}
scanf("%d",&k);
for(register int i = 1;i <= k;++ i)
{
cin >> x >> y;
use[x][y] = use[y][x] = true;
}
for(register int i = 1;i <= n;++ i)
for(register int j = 1;j <= n;++ j)
if(use[i][j] == false && f[i][j] != 999)
f[i][j] = 0;
for(register int k = 1;k <= n;++ k)
for(register int i = 1;i <= n;++ i)
for(register int j = 1;j <= n;++ j)
f[j][i] = f[i][j] = min(f[i][j],f[i][k] + f[k][j]);
int A,B;
scanf("%d%d",&A,&B);
cout << f[A][B] << endl;
return 0;
}
2.【SPFA】
【思路】
SPFA
SPFA诈尸+1
先输入有路的数据
建立边但是先不赋值
保持他默认为0的距离
只把某条边对应的长度稍微记录一下
然后输入坏掉的路
这个时候才将坏掉的路的长度赋值上去
因为完好无损的路可以通过而且不需要耗费去修复
所以对需要修复的路径的总长度没有贡献
就是0
但是坏掉的不一样
贡献它本身的长度
然后跑SPFA求出A到B的最短路就好了
【完整代码】
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int Max = 102;
struct node
{
int y;
int ne;
int z;
}a[Max * Max];
int sum = 0;
int head[Max];
int acioi[Max * Max];
void add(int x,int y,int z)
{
a[++ sum].y = y;
a[sum].ne = head[x];
acioi[sum] = z;
head[x] = sum;
}
int d[Max];
bool use[Max];
int A,B;
int n,m,k;
void SPFA()
{
queue<int>q;
q.push(A);
for(register int i = 1;i <= n;++ i)
d[i] = 999;
d[A] = 0;
while(!q.empty())
{
int qwq = q.front();
q.pop();use[qwq] = false;
for(register int i = head[qwq];i != 0;i = a[i].ne)
{
int awa = a[i].y;
if(d[awa] > d[qwq] + a[i].z)
{
d[awa] = d[qwq] + a[i].z;
if(use[awa] == false)
{
use[awa] = true;
q.push(awa);
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
int x,y,z;
for(register int i = 1;i <= m;++ i)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
scanf("%d",&k);
for(register int i = 1;i <= k;++ i)
{
scanf("%d%d",&x,&y);
for(register int j = head[x];j != 0;j = a[j].ne)
if(a[j].y == y)
a[j].z = acioi[j];
for(register int j = head[y];j != 0;j = a[j].ne)
if(a[j].y == x)
a[j].z = acioi[j];
}
scanf("%d%d",&A,&B);
SPFA();
cout << d[B] << endl;
return 0;
}
3.【dijstra】
【思路】
地杰斯特拉+堆优化
我知道的三个求最短路的方法里面貌似生存能力最强的一个
输入数据
处理方式和SPFA的方法一个样
先只把边连接起来但是不赋值边权
让边权保持为0
然后将损坏掉的路赋值上边权
(原因不多赘述了,前面两种方法都说过了)
然后跑dijkstra就好了
【完整代码】
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
struct point
{
int w;//按照w从小到大排序
int x;
bool operator < (const point & xx)const
{
return xx.w < w;
}
};
priority_queue<point>q;
const int Max = 102;
struct node
{
int y,ne,z;
}a[Max * Max];
int sum = 0;
int head[Max];
int acioi[Max * Max];
int n,m;
int A,B;
int dis[Max];
bool use[Max];
void add(int x,int y,int z)
{
a[++ sum].y = y;
a[sum].ne = head[x];
acioi[sum] = z;
head[x] = sum;
}
void dj()
{
dis[A] = 0;
q.push((point){0,A});
while(!q.empty())
{
point qwq = q.top();
q.pop();
int x = qwq.x;
if(use[x] == true)
continue;
else
use[x] = true;
for(register int i = head[x];i != 0;i = a[i].ne)
{
int awa = a[i].y;
if(dis[awa] > dis[x] + a[i].z)
{
dis[awa] = dis[x] + a[i].z;
if(use[awa] == false)
q.push((point){dis[awa],awa});
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(register int i = 1;i <= n;++ i)
dis[i] = 999;
int x,y,z;
for(register int i = 1;i <= m;++ i)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
int k;
scanf("%d",&k);
for(register int i = 1;i <= k;++ i)
{
scanf("%d%d",&x,&y);
for(register int j = head[x];j != 0;j = a[j].ne)
if(a[j].y == y)
a[j].z = acioi[j];
for(register int j = head[y];j != 0;j = a[j].ne)
if(a[j].y == x)
a[j].z = acioi[j];
}
scanf("%d%d",&A,&B);
dj();
cout << dis[B] << endl;
return 0;
}
洛谷 P3905 道路重建 题解的更多相关文章
- 洛谷——P3905 道路重建
P3905 道路重建 题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现 ...
- 洛谷 P3905 道路重建
题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...
- 洛谷P3905 道路重建
题目:https://www.luogu.org/problemnew/show/P3905 分析: 此题是显然的最短路算法,只是看到一起删掉的一堆边感到十分棘手,而且还要求出的是最短添加边的总长度 ...
- 洛谷 P4198 楼房重建 题解
题面 首先你要知道题问的是什么:使用一种数据结构,动态地维护以1为起点地最长上升子序列(把楼房的高度转化成斜率地序列)的长度: 怎么做?线段树! 我们在线段树上维护两个东西:1.这个区间内斜率的最大值 ...
- P1359 租用游艇 && P3905 道路重建 ------Floyd算法
P1359 租用游艇 原题链接https://www.luogu.org/problemnew/show/P1359 P3905 道路重建 原题链接https://www.luogu.org/ ...
- 洛谷P1119-灾后重建-floyd算法
洛谷P1119-灾后重建 题目描述 给出\(B\)地区的村庄数NN,村庄编号从\(0\)到\(N-1\),和所有\(M\)条公路的长度,公路是双向的. 给出第\(i\)个村庄重建完成的时间\(t_i\ ...
- 洛谷P2832 行路难 分析+题解代码【玄学最短路】
洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...
- 【洛谷P3960】列队题解
[洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...
- P3905 道路重建
P3905 道路重建我一开始想错了,我的是类似kruskal,把毁坏的边从小到大加,并且判断联通性.但是这有一个问题,你可能会多加,就是这条边没用,但是它比较小,你也加上了.居然还有10分,数据也是水 ...
随机推荐
- JavaScript判断是否是正确数值 isNaN
NaN在JavaScript中表示不是数字 JavaScript中isNaN函数方法是返回一个 Boolean 值,指明提供的值是否是保留值 NaN (不是数字). 使用方法:isNaN(numVal ...
- 2019 4399java面试笔试题 (含面试题解析)
本人3年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.4399等公司offer,岗位是Java后端开发,最终选择去了4399. 面试了很多家公司,感觉大部分公司考察的点 ...
- Python进阶----数据库引擎(InnoDB),表的创建,mysql的数据类型,mysql表的约束
Python进阶----数据库引擎(InnoDB),表的创建,mysql的数据类型,mysql表的约束 一丶MySQL的存储引擎 什么是存储引擎: MySQL中的数据用各种不同的技术存储在文件( ...
- Linux系统怎么分区
linux分区方法,不同的人有不同的方法,反正没有统一的方法.在分区方面,我觉得根据自己的实际情况来分是最好的.玩linux也有好几年了,下面说一下,我在分区方面的一些经验. 一,个人用 如果是个人用 ...
- Net实现阿里云开放云存储服务(OSS)
1 第一步框架搭建新建一个全新的MVC项目 (项目参考文档https://docs.aliyun.com/?spm=5176.383663.9.6.5OJI07#/pub/oss/sdk/sdk-do ...
- 【Java基础】- Java学习路线图
Java的学习路线图,整理以备自己学习和温习. 1.Java基础 具体内容: 1. 编程基础(开发环境配置.基础语法.基本数据类型.流程控制.常用工具类) 2. 面向对象(继承.封装.多态.抽象类.接 ...
- Java 之 Response 文件下载案例
文件下载需求: 1. 页面显示超链接 2. 点击超链接后弹出下载提示框 3. 完成图片文件下载 分析过程: 1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框 ...
- 物料管理混乱怎么办?APS系统帮你实现高效运输
APS系统可以高效地管理.控制分销中心并保证产品可订货.可盈利.能力可用.分销计划帮助企业分析原始信息,然后企业能够确定如何优化分销成本或者根据生产能力和成本提高客户服务水平. 今天成功的企业为了取得 ...
- 前端框架 Vue.js 概述
Vue.js 是什么 图片 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视 ...
- DNS 原理入门 - 阮一峰(转载)
DNS 原理入门 作者: 阮一峰 日期: 2016年6月16日 DNS 是互联网核心协议之一.不管是上网浏览,还是编程开发,都需要了解一点它的知识. 本文详细介绍DNS的原理,以及如何运用工具软件 ...