「BZOJ2200」[Usaco2011 Jan] 道路和航线 - 最短路+拓扑排序

->点我进原题

[Usaco2011 Jan]道路和航线


Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 1116 Solved: 410


Description

Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到T个城镇 (\(1 <= T <= 25,000\)),编号为\(1\)~\(T\)。这些城镇之间通过\(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\)) 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。

Input

\(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\)

Output

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

Sample Input

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\)

Sample Output

NO PATH
NO PATH
5
0
-95
-100

样例输出解释:

\(FJ\)的奶牛从\(4\)号城镇开始,可以通过道路到达\(3\)号城镇。然后他们会通过航线达到\(5\)\(6\)号城镇。
但是不可能到达\(1\)\(2\)号城镇。

分析

\(1\):Dijkstra+Topsort

本题是一道明显的单源最短路问题,但图中带有负权边,不能使用Dijkstra算法。若直接用SPFA算法求解,因为测试数据经过了特殊构造,所以程序无法在规定时限内输出答案。题目中有一个特殊条件——双向边都是非负的,只有单向边可能是负的,并且单向边不构成环。我们应该利用这个性质来解答本题。
如果只把双向边(道路)添加到图里,那么会形成若干个连通块。若把每个连通块整体看作一个“点”,再把单向边(航线)添加到图里,会得到一张有向无环图。在有向无环图中,无论边权正负,都可以按照拓扑排序进行扫描,在线性时间内求出单源最短路。这启发我们用拓扑排序的框架处理整个图,但在双向边构成的每个连通块内部使用堆优化的Dijkstra算法快速计算该块内的最短路信息
这样就可以在块内使用Dijkstra,块间利用拓扑排序更新答案。时间复杂度\(O(MlogN)\)

\(2\):SPFA+SLF

顺便加上了一些卡常的奇技淫巧,最慢的点为732ms,如果不了解SLF优化的可以看我的另外一篇博客->戳我

代码

\(1\)

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<iostream>
#include<queue>
#include<bits/stdc++.h>
#define rg register
using namespace std;
inline int read(){rg int f=0,x=0;rg char ch=getchar();while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();return f?-x:x;
}const int N =25010;
const int M =100010;
const int inf =0x7f7f7f7f;
#define ft first
#define sd second
int n,r,p,s,head[N],tot;
int cnt,belong[N];
int indeg[N],dis[N];
bool vis[N];
typedef pair<int ,int > pa;
vector <pa >road[N],plane[N];
vector <int >block[N];
inline void init(){for(rg int i=0;i<N;++i) dis[i]=inf;dis[s]=0;
}
inline void dfs(rg int u){belong[u]=cnt;block[cnt].push_back(u);for(int i=0;i<road[u].size();++i){int v=road[u][i].ft;if(!belong[v])  dfs(v);}   
}
inline void topsort_dij(){init();queue<int > q;for(rg int i=1;i<=cnt;++i)  if(!indeg[i])   q.push(i);while(!q.empty()){int u=q.front();q.pop();priority_queue<pa,vector<pa>,greater<pa> > pq;for(int i=0;i<block[u].size();++i)if(dis[block[u][i]]!=inf)pq.push(make_pair(dis[block[u][i]],block[u][i]));while(!pq.empty()){int u=pq.top().sd;pq.pop();if(vis[u]) continue;vis[u]=true;for(int i=0;i<road[u].size();++i)if(dis[u]+road[u][i].sd<dis[road[u][i].ft])pq.push(make_pair(dis[road[u][i].ft]=dis[u]+road[u][i].sd,road[u][i].ft));for(int i=0;i<plane[u].size();++i)dis[plane[u][i].ft]=min(dis[plane[u][i].ft],dis[u]+plane[u][i].sd);}for(int i=0;i<block[u].size();++i)for(int j=0;j<plane[block[u][i]].size();++j)if(--indeg[belong[plane[block[u][i]][j].ft]]==0)q.push(belong[plane[block[u][i]][j].ft]);}
}
signed main(){n=read(),r=read(),p=read(),s=read();for(rg int i=1,u,v,w;i<=r;++i){u=read(),v=read(),w=read();road[u].push_back(make_pair(v,w));road[v].push_back(make_pair(u,w));}for(rg int i=1;i<=n;++i)if(!belong[i]){++cnt;dfs(i);}for(rg int i=1,u,v,w;i<=p;++i){u=read(),v=read(),w=read();plane[u].push_back(make_pair(v,w));++indeg[belong[v]];}topsort_dij(); for(rg int i=1;i<=n;++i)if(dis[i]==inf) printf("NO PATH\n");else    printf("%d\n",dis[i]);return 0;
}

\(2\)

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<iostream>
#include<queue>
#define rg register
using namespace std;
inline int read(){rg int f=0,x=0;rg char ch=getchar();while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();return f?-x:x;
}const int N =25010;
const int M =150010;
const int inf =0x7f7f7f7f;
int n,r,p,s,head[N],tot,dis[N];
bool vis[N];
struct edge{int to,nxt,w;
}e[M];
inline void add(rg int u,rg int v,rg int w){e[++tot].to=v;e[tot].w=w;e[tot].nxt=head[u];head[u]=tot;
}
inline void spfa(rg int s){for(rg int i=1;i<=n;++i)    dis[i]=inf;dis[s]=0;deque<int > q;q.push_back(s);while(!q.empty()){int u=q.front();q.pop_front();vis[u]=false;for(rg int i=head[u];i;i=e[i].nxt){int v=e[i].to;if(dis[v]>dis[u]+e[i].w){dis[v]=dis[u]+e[i].w;if(!vis[v]){vis[v]=true;if(q.empty()||dis[v]>dis[q.front()])    q.push_back(v);else    q.push_front(v);}}}}}
signed main(){n=read(),r=read(),p=read(),s=read();for(rg int i=1;i<=r;++i){int u=read(),v=read(),w=read();add(u,v,w),add(v,u,w);}for(rg int i=1;i<=p;++i){int u=read(),v=read(),w=read();add(u,v,w);}spfa(s);for(rg int i=1;i<=n;++i)if(dis[i]==inf) printf("NO PATH\n");else    printf("%d\n",dis[i]);return 0;
}

转载于:https://www.cnblogs.com/horrigue/p/9641636.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/426840.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哈佛大学计算机科学专,哈佛大学计算机科学专业

哈佛大学计算机科学专业通过哈佛文理研究生院申请并统一管理&#xff0c;要求申请者递交GRE成绩&#xff0c;但并无最低GRE分数要求。该项目设有BA/MS、PhD两个项目。所有PhD学生均可以获得全额奖学金&#xff0c;但不向硕士学生发放奖学金。哈佛大学计算机科学专业设置计算机架…

excel亮灯怎么设置_Excel表格技巧—怎么给表格设置密码

很多 Excel 表格里都有一些重要信息&#xff0c;但是当我们给别人发Excel表格时&#xff0c;别人可能会不小心或者故意更改表中数据。怎么才能避免这些表格的数据被更改呢&#xff1f;小编在这里和大家分享一个技巧&#xff1a;给表格设置密码&#xff01;如下图&#xff0c;假…

Collection和Collections的区别是什么

1&#xff09;java.util.Collection是一个集合顶层接口&#xff0c;该接口的设计目的是为各种具体的集合提供最大化的统一的操作方式&#xff0c;它提供了对集合对象进行基本操作的通用接口方法&#xff0c;实现该接口的类主要有List和Set 2&#xff09;java.util.Collections是…

实例36:python

#题目&#xff1a;求100之内的素数。 #!/usr/bin/python -- coding: UTF-8 -- 输出指定范围内的素数 用户输入数据 lower int(input("输入区间最小值: ")) upper int(input("输入区间最大值: ")) for num in range(lower,upper 1): # 素数大于 1 …

南川职业学校计算机职业,2018年重庆五年制大专中职学校介绍——重庆市南川隆化职业中学校...

2021年高职单招升学一对一咨询高职单招王老师:17725052174(微信)2018年重庆五年制大专中职学校介绍——重庆市南川隆化职业中学校什么是五年制大专&#xff1a;五年制大专也称为五年高职或五年一贯制大专&#xff0c;是高等职业技术学院的一种招生模式&#xff0c;学制五年&…

normalize函数_提取棋盘格角点函数解析

点击上方“Qt学视觉”&#xff0c;选择“星标”公众号重磅干货&#xff0c;第一时间送达共同学习共同进步1、如何查阅OpenCV官方说明文档查阅地址&#xff1a;https://docs.opencv.org/4.3.0/我这里使用的是OpenCV4.3&#xff0c;所以我需要查阅的就是4.3版本的说明文档上图就是…

STM32三种启动模式 boot0 boot1

STM32三种启动模式对应的存储介质均是芯片内置的&#xff0c;它们是&#xff1a; 1&#xff09;用户闪存芯片内置的Flash。2&#xff09;SRAM芯片内置的RAM区&#xff0c;就是内存啦。3&#xff09;系统存储器芯片内部一块特定的区域&#xff0c;芯片出厂时在这个区域预置了一段…

实例37:python

#对10个数进行排序。 #!/usr/bin/python -- coding: UTF-8 -- print (‘请输入10个数字:\n’) a[] for n in range(10): a.append(int(input(‘输入一个数字:\n’))) for i in range(0,9): mini for j in range(i1,10): if a[min]>a[j]: minj if min!i: ta[min] a[min]a[i…

南京二本有什么计算机学校,南京有什么好的二本学校?

南京是六朝古都&#xff0c;历史底蕴深厚。南京市高等教育资源丰富。南京市有高校53所&#xff0c;其中本科院校35所&#xff0c;35所&#xff0c;本科院校中&#xff0c;民办本科院校10所&#xff0c;公办本科院校25所。25所公办本科院校中&#xff0c;一本院校占多数&#xf…

阿联酋esma认证怎么做_行业视野 | 关于阿联酋eCall 的要求更新

行业视野 | 关于阿联酋eCall 的要求更新背景&#xff1a;根据2018年底阿联酋标准与计量局ESMA发布的通知&#xff0c;自2020年起所有出口到阿联酋的2021MY轻型车辆需安装eCall系统&#xff0c;并满足阿联酋相关法规要求。必维集团汽车服务部致力于为国内企业消除认证壁垒&#…

实例38:python

#题目&#xff1a;求一个3*3矩阵主对角线元素之和。 #程序分析&#xff1a;利用双重for循环控制输入二维数组&#xff0c;再将a[i][i]累加后输出。 #!/usr/bin/python -- coding: UTF-8 -- if name ‘main’: a [] sum 0.0 for i in range(3): a.append([]) for j in ran…

Bootstrap table后端分页(ssm版)

说明bootstrap table可以前端分页&#xff0c;也可以后端sql用limit分页。这里讲的是后端分页&#xff0c;即实用limit。性能较好&#xff0c;一般均用这种源码下载地址&#xff1a;https://git.oschina.net/dshvv/pagination_byjava.git该文主要讲后端分页&#xff1a;1、前端…

初中计算机课程计划,最新2020年度初中信息技术教学计划(精选3篇).doc

初中信息技术教学计划(精选3篇)初中信息技术教学计划1一、学生基本情况本计划针对七年级全体学生&#xff0c;通过上年的学习&#xff0c;学生对办公软件例如word、excel有一定了解&#xff0c;但是由于每一学期信息技术课时比较少&#xff0c;每周只有一节课&#xff0c;学生的…

dart 乘方运算符_Dart系列-运算符

周末学习了一下Dart语言&#xff0c;按照慕课网Flutter开发第一步-Dart编程语言入门教程进行学习&#xff0c;所以记录一下&#xff0c;感觉慕课网的老师辛苦做的视频教程&#xff0c;说得很清楚&#xff0c;有基础学起来很轻松也很快&#xff0c;本篇来学习dart的运算符。算术…

实例39:python

#题目&#xff1a;有一个已经排好序的数组。现输入一个数&#xff0c;要求按原来的规律将它插入数组中。 #程序分析&#xff1a;首先判断此数是否大于最后一个数&#xff0c;然后再考虑插入中间的数的情况&#xff0c;插入后此元素之后的数&#xff0c;依次后移一个位置。 #程…

6.0动态加载权限用PermissionGen

ndroid 6.0 新增加了运行时的动态添加权限&#xff0c;在此介绍一个第三方库&#xff0c;PermissionGen&#xff0c;可以很方便简洁的增加 6.0权限 首先给大家上 PermissionGen 库地址&#xff1a;https://github.com/lovedise/PermissionGen 下面给大家详细介绍它的使用&…

量子计算机具有天热的,量子绝热计算

摘要&#xff1a;本文在GNU/Linux 平台上基于Libquantum C 编译的环境实现了比QSS(Quantum System Simulator)精度高的量子绝热SAT(satisfiability problem)算法。通过选择Ising 模型的一个简化的Hamiltonian 量,在量子绝热SAT 算法中的精度得到进一步的加强。 第二章,介绍了量…

实例40:python

#将一个数组逆序输出 #!/usr/bin/python -- coding: UTF-8 -- a[0,1,2,3,4,5,6,7,8,9] for i in range(0,10): print(a.pop(),end’’)

python第三方库全部_自动更新Python所有第三方库

一般python用得比较久以后&#xff0c;就会安装很多第三方的库。比如这是我的pip list情况&#xff1a;pip list而且一屏还显示不完。通过如下命令可以看到需要更新的第三方库&#xff1a;pip list -o需要更新的库而pip提供的更新命令只能一个个的更新...pip install -U 库名 #…

2018.09.15 vijos1053Easy sssp(最短路)

传送门 貌似可以最短路时同时判定负环啊。 但我不想这样做。 于是写了一个dfs版的判环&#xff0c;bfs版的求最短路。 代码&#xff1a; #include<iostream> #include<cctype> #include<cstdio> #include<cstring> #include<queue> #define …