AcWing342. 道路与航线
解题思路
这题用\(SPFA\)会被卡,所以我们不能用\(SPFA\)
但是观察数据我们可以发现对于道路,\(0≤C_i≤10^{5}\)
所以对于每个连通块(内部不存在航线),我们可以用\(Dijkstra\)算法进行求解,因为不存在负权边,而\(Dijkstra\)算法的时间较为稳定,所以对于连通块内部的最短路,我们采用\(Dijkstra\)
块内问题解决了,但是块间呢
保证如果有一条航线可以从\(A_i\) 到 \(B_i\),那么保证不可能通过一些道路和航线从 \(B_i\) 回到 \(A_i\)。
我们将每个连通块看做一个大点
那么根据上述性质,我们可以得到这张由大点为点,航线为边的图是一张拓扑图\((DAG)\)
那么\(DAG\)的最短路我们可以按照它的拓扑序扫描求出最短路
为什么呢
因为我们利用拓扑序进行\(DP\),那后来的节点一定是无法更新前面的节点,这样就可以确保无后效性,因此可以正确求出最短路
解题步骤
1.先输入所有的双向道路,然后用\(dfs\)求出所有的连通块,用\(id[]\)数组统计每个数所在的连通块编号,用一个\(vector\)<\(int\)> \(block[]\)来保存每个编号的连通块里存的点
2.输入所有的航线,再输入的同时可以统计每个连通块的入度
3.拓扑排序
4.按照拓扑序对每个连通块进行\(Dijkstra\)算法
5.\(Dijkstra\)步骤:
(1)每次从堆中取出一个点\(t\)
(2)遍历\(t\)的所有出边,同一个连通块的进行松弛操作,不同连通块的将对方连通块入度\(-1\),如果\(-1\)后连通块的入度为0,插入拓扑序队列中(所以拓扑序的队列要开成全局的)
代码
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 25010, M = 2e5 + 10, INF = 0x3f3f3f3f;
int h[N], e[M], w[M], ne[M], idx;
int dist[N], id[N], st[N], din[N];
int n, mr, mp, S, bcnt;
vector<int> block[M];
queue<int> q;
void add(int a, int b, int c)
{
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}
void dfs(int u, int bid)
{
id[u] = bid, block[bid].push_back(u);
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (!id[j]) dfs(j, bid);
}
}
void Dijkstra(int bid)
{
priority_queue<PII, vector<PII>, greater<> > heap;
for (auto u : block[bid])
heap.push({dist[u], u});
while (heap.size())
{
auto t = heap.top().second; heap.pop();
if (st[t]) continue ;
st[t] = true ;
for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
if (id[j] == id[t]) heap.push({dist[j], j});
}
if (id[j] != id[t] && -- din[id[j]] == 0) q.push(id[j]);
}
}
}
void topsort()
{
memset(dist, 0x3f, sizeof dist);
dist[S] = 0;
for (int i = 1; i <= bcnt; i ++ )
if (!din[i]) q.push(i);
while (q.size())
{
int t = q.front(); q.pop();
Dijkstra(t);
}
}
int main()
{
scanf("%d%d%d%d", &n, &mr, &mp, &S);
memset(h, -1, sizeof h);
memset(st, 0, sizeof st);
while (mr -- )
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w), add(v, u, w);
}
for (int i = 1; i <= n; i ++ )
if (!id[i]) dfs(i, ++ bcnt);
while (mp -- )
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w), din[id[v]] ++ ;
}
topsort();
for (int i = 1; i <= n; i ++ )
if (dist[i] > INF / 2) puts("NO PATH");
else printf("%d\n", dist[i]);
return 0;
}
AcWing342. 道路与航线的更多相关文章
- 2200: [Usaco2011 Jan]道路和航线 (拓扑排序+dijstra)
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- BZOJ 2200--[Usaco2011 Jan]道路和航线(最短路&拓扑排序)
2200: [Usaco2011 Jan]道路和航线 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1128 Solved: 414[Submit] ...
- BZOJ2200 道路和航线【好题】【dfs】【最短路】【缩点】
2200: [Usaco2011 Jan]道路和航线 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1384 Solved: 508[Submit] ...
- [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- bzoj2200道路和航线
试题描述 Farmer John 正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到 T (1≤T≤2.5×10^4)个城镇 ,编号为 1 到 T.这些城镇之间通过 R 条道路(编号为 1 ...
- bzoj 2200: [Usaco2011 Jan]道路和航线——拓扑+dijkstra
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- [Usaco2011 Jan]道路和航线
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- BZOJ 2200: [Usaco2011 Jan]道路和航线
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- BZOJ 2200 道路与航线(图论)
BZOJ 2200 道路与航线 题目大意 有两种路,一种没负数,一种没环,求单源最短路. solution 存在负边权Dij一定不能用嘛,显然不是 根据题意能看出来是tarjan,将双向边缩点,得到的 ...
- BZOJ2200 道路与航线 题解
题目 Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 \((1 <= T <= 25,000)\),编号为\(1T\).这些城镇之间通过\(R ...
随机推荐
- 改善C#程序的方法-3 比较器和LINQ排序
一 创建对象时考虑实现比较器 假设有这样的场景,有一个40个人的学生列表,业务中需针对学生的成绩来进行排序. 可以考虑用IComparable接口和ICompare接口实现: class Progra ...
- 关于aws上ec2机型的种类总结汇总
在aws上ec2的机型是非常多的,但主要的种类为如下几种 General Purpose (通用型) ...
- 『现学现忘』Git后悔药 — 34、git commit --amend 命令
目录 1.git commit --amend 命令说明 2.使用场景 (1)场景一 (2)场景二 3.git commit --amend 命令原理 这是我们Git中的第三种后悔药. 1.git c ...
- laravel 报错 AUTH` failed: ERR Client sent AUTH, but no password is set
明明没有设置redis密码.访问时候却报错 在代码里面的databases.php 改成这样就可以了.predis新版也会有取不到passwor的时候.改成我截图那样也可以.他默认取的是default ...
- Vue学习之--------Vue生命周期beforeCreate、created、beforeMount、mounted、beforeDestroy 。。。(图解详细过程)(2022/7/17)
文章目录 1.Vue生命周期 1.1 概念 1.2 图解 2.钩子函数的用法说明 2.1 beforeCreate()和created()的详细讲述 2.1.1 方法说明 2.1.2 代码实例 2.1 ...
- 一天十道Java面试题----第一天(面向对象-------》ArrayList和LinkedList)
这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.面向对象 2.JDK.JRE.JVM区别和联系 3.==和equals 4.final 5.String .Strin ...
- SpringCloud微服务实战——搭建企业级开发框架(四十八):【移动开发】整合uni-app搭建移动端快速开发框架-使用第三方UI框架
uni-app默认使用uni-ui全端兼容的.高性能UI框架,在我们开发过程中可以满足大部分的需求了,并且如果是为了兼容性,还是强烈建议使用uni-ui作为UI框架使用. 如果作为初创公司,自 ...
- vue-axios增加操作
<template> <div class="Insert"> <label for="name">名称:</labe ...
- onps栈移植说明(3)——添加网卡
4. 添加网卡 移植的最后一步就是编写网卡驱动然后将网卡添加到协议栈.网卡驱动其本质上完成的是数据链路层的工作,在整个通讯链路上处于通讯枢纽位置,通讯报文的发送和接收均由其实际完成.针对网卡部分的移植 ...
- java学习之MybBaits
0x00前言 我前面使用的jdbc和jdbc的工具类集成的但是它们在少部分代码的情况下会会简单,但是以后如果项目较大jdbc的固定代码会很难维护,如果使用框架会简单很多,也标志着java学习正式进入到 ...