题目

Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到T个城镇 \((1 <= T <= 25,000)\),编号为\(1T\)。这些城镇之间通过\(R\)条道路 \((1 <= R <= 50,000\),编号为\(1\)到\(R\)) 和\(P\)条航线 \((1 <= P <= 50,000\),编号为\(1\)到\(P\)) 连接。每条道路i或者航线\(i\)连接城镇\(A_i (1 <= A_i <= T)\)到B\(_i (1 <= B_i <= T)\),花费为\(C_i\)。对于道路,\(0 <= C_i <= 10,000\);然而航线的花费很神奇,花费\(C_i\)可能是负数\((-10,000 <= C_i <= 10,000)\)。道路是双向的,可以从\(A_i\)到\(B_i\),也可以从\(B_i\)到\(A_i\),花费都是\(C_i\)。然而航线与之不同,只可以从\(A_i\)到\(B_i\)。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台了一些政策保证:如果有一条航线可以从\(A_i\)到\(B_i\),那么保证不可能通过一些道路和航线从\(B_i\)回到\(A_i\)。由于FJ的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇\(S(1 <= S <= T)\) 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。

输入格式

  • 第\(1\)行:四个空格隔开的整数:$ T, R, P$, and \(S\)

  • 第\(2\)到\(R+1\)行:三个空格隔开的整数(表示一条道路):\(A_i, B_i 和 C_i\)

  • 第\(R+2\)到\(R+P+1\)行:三个空格隔开的整数(表示一条航线):\(A_i, B_i\) 和 \(C_i\)

输出格式

  • 第1到T行:从S到达城镇i的最小花费,如果不存在输出"NO PATH"。

输入样例

6 3 3 4
1 2 5
3 4 5
5 6 10
3 5 -100
4 6 -100
1 3 -10

样例输入解释

一共六个城镇。在1-2,3-4,5-6之间有道路,花费分别是5,5,10。同时有三条航线:3->5,4->6和1->3,花费分别是-100,-100,-10。FJ的中心城镇在城镇4。

输出样例


NO PATH
NO PATH
5
0
-95
-100

样例输出解释

FJ的奶牛从4号城镇开始,可以通过道路到达3号城镇。然后他们会通过航线达到5和6号城镇。

但是不可能到达1和2号城镇。

题解

因为有负权存在, 所以不能用 Dijkstra 算法, 而且这道题还故意卡掉了 SPFA, 所以必须用别的方法.

注意, 题目中有一个特性, 双向边都是负的, 单向边都是正的, 而且构不成环.

如果把图中的单向边删掉, 只留下双向边, 那么就剩下来一些连通块, 因为全是双向边, 所以只要存在边, 就是联通的.

然后用类似 Tarjan 的办法, 把强连通分量看作一个点, 然后再添加单向边后, 就是一个有向无环图(DAG), 然后使用拓扑排序处理整个图, 使用 Dijkstra 处理每个连通块.

首先只加入双向边, DFS 求每个连通块, 根据输入的特性, 输入完道路之后 DFS 即可.

然后对于每个连通块, 和拓扑排序一样, 统计入度, 将入度为0的连通块加入队列.

不断从队列中取出一个连通块, 进行 Dijkstra 松弛, 入度减一, 如果为0, 加入队列.

那么怎么进行 Dijkstra 松弛呢?

最开始定义一个数组, \(d_i\)表示\(S\)到\(i\)的最短路, 最开始\(d_S=0\),其它初始化为无穷大.

拿到一个连通块之后, 把所有的点都加入优先队列,

不断从优先队列中取出\(d\)最小的点, 扫描每条出边, 进行松弛操作, 如果扫描到的出边终点不在此连通块, 就把终点所属连通块加入拓扑排序队列.

拓扑排序队列为空后, \(d\)数组就是要求的答案.

代码

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXT = 25006, MAXRP = 150006, INF = 0x3f3f3f3f;
struct edges { int next, value, to;} edges[MAXRP];
int T, R, P, S, A, B, C, head[MAXT], tot = 0, c[MAXT], deg[MAXT], d[MAXT], totc = 0;
bool v[MAXT];
queue<int> q;
priority_queue<pair<int, int> > Q;
inline void add(int x, int y, int v) {
edges[++tot].to = y;
edges[tot].value = v;
edges[tot].next = head[x];
head[x] = tot;
}
void dfs(int i) {
for (int j = head[i]; j; j = edges[j].next)
if (!c[edges[j].to]) c[edges[j].to] = totc, dfs(edges[j].to);
}
int main() {
memset(d, 0x7f, sizeof(d));
scanf("%d%d%d%d",&T,&R,&P,&S);
for (int i = 1; i <= R; i++)
scanf("%d %d %d", &A, &B, &C), add(A, B, C), add(B, A, C);
for (int i = 1; i <= T; i++)
if (!c[i]) c[i] = ++totc, dfs(i);
for (int i = 1; i <= P; i++)
scanf("%d %d %d", &A, &B, &C), add(A, B, C), ++deg[c[B]];
q.push(c[S]);
for (int i = 1; i <= totc; i++)
if (!deg[i]) q.push(i);
d[S] = 0;
while (q.size()) {
int i = q.front();
q.pop();
for (int j = 1; j <= T; j++)
if (c[j] == i) Q.push(make_pair(-d[j], j));
while (Q.size()) {
int x = Q.top().second;
Q.pop();
if (v[x]) continue;
v[x] = 1;
for (int j = head[x]; j; j = edges[j].next) {
int y = edges[j].to;
if (d[x] + edges[j].value < d[y]) {
d[y] = d[x] + edges[j].value;
if (c[x] == c[y]) Q.push(make_pair(-d[y], y));
}
if (c[x] != c[y] && !--deg[c[y]]) q.push(c[y]);
}
}
}
for (int i = 1; i <= T; i++) (d[i] > INF) ? puts("NO PATH") : printf("%d\n", d[i]);
return 0;
}

BZOJ2200 道路与航线 题解的更多相关文章

  1. BZOJ2200 道路和航线【好题】【dfs】【最短路】【缩点】

    2200: [Usaco2011 Jan]道路和航线 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1384  Solved: 508[Submit] ...

  2. bzoj2200道路和航线

    试题描述 Farmer John 正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到 T (1≤T≤2.5×10^4)个城镇 ,编号为 1 到 T.这些城镇之间通过 R 条道路(编号为 1 ...

  3. 2200: [Usaco2011 Jan]道路和航线 (拓扑排序+dijstra)

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  4. BZOJ 2200--[Usaco2011 Jan]道路和航线(最短路&拓扑排序)

    2200: [Usaco2011 Jan]道路和航线 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1128  Solved: 414[Submit] ...

  5. [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  6. bzoj 2200: [Usaco2011 Jan]道路和航线——拓扑+dijkstra

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  7. [Usaco2011 Jan]道路和航线

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  8. BZOJ 2200: [Usaco2011 Jan]道路和航线

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  9. BZOJ 2200 道路与航线(图论)

    BZOJ 2200 道路与航线 题目大意 有两种路,一种没负数,一种没环,求单源最短路. solution 存在负边权Dij一定不能用嘛,显然不是 根据题意能看出来是tarjan,将双向边缩点,得到的 ...

随机推荐

  1. python numpy 库

    引用文章:https://blog.csdn.net/xjl271314/article/details/80409034

  2. jenkins 添加用户管理权限

    一.前言 小组开会通知 想把jenkins 构建的权限给开发,这样的话效率会增加.运维也不必每次帮助开发去构建发布. 1.规划 jenkins 四个项目分别对应三个人负责.项目下的只负责 CI.UAT ...

  3. 制作seata docker镜像

    seata是阿里巴巴的一款开源的分布式事务框架,官方已经支持docker了,但是因为业务的需要,需要自己定制. 制作docker镜像 官方的Dockerfile.下载seata-server-1.1. ...

  4. CSS学习:overflow:hidden解决溢出,坍塌,清除浮动

    overflow:hidden是overflow属性的一个神奇用法,它可以帮助我们隐藏溢出的元素,清除浮动和解除坍塌. CSS样式: .container{ background-color: bla ...

  5. WPF中DataTemplateSelector的简单应用

    WPF中DataTemplateSelector的简单应用 DataTemplateSelector中文叫数据模板选择器,根据数据模型内的属性值选择不同的数据模板,多用于容器如listbox中,达到同 ...

  6. 循序渐进VUE+Element 前端应用开发(10)--- 基于vue-echarts处理各种图表展示

    在我们做应用系统的时候,往往都会涉及图表的展示,综合的图表展示能够给客户带来视觉的享受和数据直观体验,同时也是增强客户认同感的举措之一.基于图表的处理,我们一般往往都是利用对应第三方的图表组件,然后在 ...

  7. Elasticsearch去重查询/过滤重复数据(聚合)

    带家好,我是马儿,这次来讲一下最近遇到的一个问题 我司某个环境的es中被导入了重复数据,导致查询的时候会出现一些重复数据,所以要我们几个开发想一些解决方案,我们聊了聊,相出了下面一些方案: 1.从源头 ...

  8. debug PostgreSQL 9.6.18 using Eclipse IDE on CentOS7

    目录 debug PostgreSQL 9.6.18 using Eclipse IDE on CentOS7 1.概览 2.建立用户 3.编译postgre 4.启动Eclipse 5.设置环境变量 ...

  9. 汇编字符串末尾以00H或 0AH和00H结尾

    例如:db 'hello',0 用 C 语言百定义字符串时,编译软件会自动在字符串的末尾,加上一个零('\0').作为度字符串结束的标记. 用汇编的 DB 伪指令定义字符串,编译软件没有自动加上零的功 ...

  10. Shell 脚本学习(1)

    一 Shell概览 1. 自动化批量系统初始化程序(update, 软件安装,时区设置,安全策略,...) 2. 自动化批量软件部署程序(LAMP,LNMP,Tomcat,LVS,Nginx) 3. ...