洛谷 [P3008] 道路与航线
最短路
因为有负权边,所以不能 dijkstra ,本题数据还卡 SPFA
但是我们发现,有负权的都是有向边,而且如果把无向边连成的联通块看成一个点的话,有向边就连成了一个 DAG,所以我们可以对所有的联通块用dij求最短路
在 DAG上用拓扑序求最短路
注意:
堆优化的 Dijkstra 在定义的结构体重载运算符的时候注意相反
因为存在负权边,所以两点不可达,不等价于两点间的距离 == inf ,应为 两点间的距离大于一个很大的数
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 100005;
int init() {
int rv = 0, fh = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') fh = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
rv = (rv<<1) + (rv<<3) + c - '0';
c = getchar();
}
return fh * rv;
}
int head[MAXN], n, m1, m2, s, nume, id[MAXN], tot, dis[MAXN], cnt[MAXN];
bool f[MAXN];
vector <int> ve[25005];
struct edge{
int to, nxt, dis;
}e[MAXN<<1];
void adde(int from, int to, int dis) {
e[++nume].to = to;
e[nume].nxt = head[from];
e[nume].dis = dis;
head[from] = nume;
}
void dfs(int u) {
if(id[u]) return;
id[u] = tot;
ve[tot].push_back(u);
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
dfs(v);
}
}
struct node{
int num, val;
bool operator < (const node & b) const{
return val > b.val;
}
};
priority_queue <node> q;
queue <int> qq;
void dij(int x){
for(int i = 0; i < (int)ve[x].size(); i++) q.push((node){ve[x][i], dis[ve[x][i]]});
while(!q.empty()) {
node u = q.top(); q.pop();
if(f[u.num]) continue;
f[u.num] = 1;
for(int i = head[u.num]; i; i = e[i].nxt) {
node v;
v.num = e[i].to;
if(id[v.num] == id[u.num] && dis[v.num] > dis[u.num] + e[i].dis) {
dis[v.num] = dis[u.num] + e[i].dis;
v.val = dis[v.num];
q.push(v);
}
if(id[v.num] != id[u.num]) {
dis[v.num] = min(dis[v.num], dis[u.num] + e[i].dis);
cnt[id[v.num]]--;
if(!cnt[id[v.num]]) {
qq.push(id[v.num]);
}
}
}
}
}
int main() {
n = init(); m1 = init(); m2 = init(); s = init();
for(int i = 1; i <= m1; i++) {
int u = init(), v = init(), di = init();
adde(u, v, di); adde(v, u, di);
}
for(int i = 1; i <= n; i++) {if(!id[i]) tot++;dfs(i);}
for(int i = 1; i <= m2; i++) {
int u = init(), v = init(), di = init();
adde(u, v, di);cnt[id[v]]++;
}
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
for(int i = 1; i <= tot; i++) if(!cnt[i]) qq.push(i);
while(!qq.empty()) {
int v = qq.front(); qq.pop();
dij(v);
}
for(int i = 1; i <= n; i++) {
if(dis[i] > 100000000) printf("NO PATH\n");
else printf("%d\n", dis[i]);
}
return 0;
}
洛谷 [P3008] 道路与航线的更多相关文章
- 【题解】洛谷P1070 道路游戏(线性DP)
次元传送门:洛谷P1070 思路 一开始以为要用什么玄学优化 没想到O3就可以过了 我们只需要设f[i]为到时间i时的最多金币 需要倒着推回去 即当前值可以从某个点来 那么状态转移方程为: f[i]= ...
- 洛谷 P3905 道路重建
题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现在有两个重要城市A和B ...
- 洛谷 [HNOI2014]道路堵塞 解题报告
[HNOI2014]道路堵塞 题意 给一个有向图并给出一个这个图的一个\(1\sim n\)最短路,求删去这条最短路上任何一条边后的最短路. 又事SPFA玄学... 有个结论,新的最短路一定是\(1\ ...
- 洛谷P1070 道路游戏(dp+优先队列优化)
题目链接:传送门 题目大意: 有N条相连的环形道路.在1-M的时间内每条路上都会出现不同数量的金币(j时刻i工厂出现的金币数量为val[i][j]).每条路的起点处都有一个工厂,总共N个. 可以从任意 ...
- 【刷题】洛谷 P4320 道路相遇
题目描述 在 H 国的小 w 决定到从城市 \(u\) 到城市 \(v\) 旅行,但是此时小 c 由于各种原因不在城市 \(u\),但是小 c 决定到在中途与小 w 相遇 由于 H 国道路的原因,小 ...
- 洛谷 P1070 道路游戏 解题报告
P1070 道路游戏 题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有\(n\)个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依 ...
- 洛谷——P3905 道路重建
P3905 道路重建 题目描述 从前,在一个王国中,在n个城市间有m条道路连接,而且任意两个城市之间至多有一条道路直接相连.在经过一次严重的战争之后,有d条道路被破坏了.国王想要修复国家的道路系统,现 ...
- 洛谷P2052 道路修建
P2052 道路修建 题目描述 在 W 星球上有 n 个国家.为了各自国家的经济发展,他们决定在各个国家 之间建设双向道路使得国家之间连通.但是每个国家的国王都很吝啬,他们只愿 意修建恰好 n – 1 ...
- 洛谷P1070 道路游戏
P1070 道路游戏 题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将 ...
随机推荐
- 从输入url到页面加载完成发生了什么详解
这是一道经典的面试题,这道题没有一个标准的答案,它涉及很多的知识点,面试官会通过这道题了解你对哪一方面的知识比较擅长,然后继续追问看看你的掌握程度.当然我写的这些也只是我的一些简单的理解,从前端的角度 ...
- Vue 后台管理
这里是结合vue和element快速成型的一个demo 里面展示了基本的后台管理界面的大体结构和element的基本操作 GitHub的地址:https://github.com/wwwming/ad ...
- 小试牛刀,建立jsp网页与导出war包
一.建立jsp网页 首先创建一个动态项目(我们学习的是动态网) 二.检查编码utf-8有没错误. 如有错误就是没有设置eclipse,请按照eclipse设置 编写一段代码,进行了解 三.导出一个wa ...
- 使用lua做序列化和反序列化
-- lua对象序列化 function serialize(obj) local lua = "" local t = type(obj) if t == "numbe ...
- Search and Replace -freecodecamp算法题目
Search and Replace 1.要求 使用给定的参数对句子执行一次查找和替换,然后返回新句子. 第一个参数是将要对其执行查找和替换的句子. 第二个参数是将被替换掉的单词(替换前的单词). 第 ...
- NOIP模拟赛 不等数列
[题目描述] 将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”.问在所有排列中,有多少个排列恰好有k个“<”.答案对2012取模. [输入格式] 第一行 ...
- [51Nod] 1218 最长递增子序列 V2
如何判断一个元素是否一定在LIS中?设f[i]为以ai结尾的LIS长度,g[i]为以ai开头的LIS长度,若f[i]+g[i]-1==总LIS,那么i就一定在LIS中出现 显然只出现一次的元素一定是必 ...
- MySQL创建数据库,用户,赋予权限
CREATE DATABASE 'voyager'; CREATE DATABASE `voyager`; CREATE USER 'dog'@'localhost' IDENTIFIED BY '1 ...
- C++:100阶乘数组输出
#include <iostream> using namespace std; int main(){ int i =1; int a[2048]={0}; while(i !=101) ...
- python计算机基础(三)
简述Python垃圾回收机制: 当x=10,赋值x=11,的代码,也就是10没有对应的变量名, 10在python眼中相当于垃圾,就会被清理掉,释放内存. 对于下述代码: x = 10 y = 10 ...