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 ...
随机推荐
- 一个 dubbo 和 springboot 的兼容性问题
背景介绍 最近把dubbo的版本从2.7.3升级到2.7.15时,遇到一个报错 No application config found or it's not a valid config! ,对应的 ...
- GC plan_phase二叉树挂接的一个算法
楔子 在看GC垃圾回收plan_phase的时候,发现了一段特殊的代码,仔细研究下得知,获取当前数字bit位里面为1的个数. 通过这个bit位为1的个数(count),来确定挂接当前二叉树子节点的一个 ...
- 2022.2.26A组总结&反思
今天的发挥比较奇妙.. T1:一眼dp+高斯消元,但是感觉细节比较多,然后先去做了T2,写完后回来推了一下就做出来了.比较裸,但是细节确实多,但是很可惜的一点是最后提交的代码没有判不合法,到手的100 ...
- [Oracle]复习笔记-SQL部分内容
Oracle笔记--SQL部分 整体框架 语句的执行顺序:from →where →group by→having→select→order by select * from * where * gr ...
- jenkins集成基于maven的javaweb项目,部署到docker容器中
使用开源工具:Jenkins,码云gitee,docker,docker页面管理工具PortainerUI,github 各种工具的安装就不必介绍了,首先打开Jenkins,刚安装完Jenkins,可 ...
- 19.-哈希算法&注册登录
一.哈希算法 哈希: 给定明文-计算出一段定长的-不可逆的值 定长输出:不管明文输入多少,哈希都是定长的 不可逆:无法反向计算出对应的明文 雪崩效应:输入改变,输出必然变 md5:32位16进制 ...
- HTML躬行记(3)——WebRTC视频通话
WebRTC 在创建点对点(P2P)的连接之前,会先通过信令服务器交换两端的 SDP 和 ICE Candidate,取两者的交集,决定最终的音视频参数.传输协议.NAT 打洞方式等信息. 在完成媒体 ...
- Python基础之面向对象:1、面向对象及编程思想
一.人狗大战 1.需求 用代码模拟人.狗打架的小游戏 人和狗种类不同,因此双方的属性各不相同 推导一: 人和狗各有不同属性 使用字典方式储存属性较为方便,并可储存多种属性 # 1.在字典内储存'人'属 ...
- Django系列---开发二
django.contrib.auth Django的用户验证框架,可以快速实现用户信息验证.登录.登出等用户操作 from django.contrib.auth import authentica ...
- .NET 7 AOT 的使用以及 .NET 与 Go 互相调用
目录 背景 C# 部分 环境要求 创建一个控制台项目 体验 AOT 编译 C# 调用库函数 减少体积 C# 导出函数 C# 调用 C# 生成的 AOT Golang 部分 安装 GCC Golang ...