->点我进原题

[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

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

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

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

  2. 算法提高课-图论-单源最短路的综合应用-AcWing 342. 道路与航线:最短路dijkstra、拓扑排序 、综合题、好题

    题目分析 来源:acwing 分析: 道路:双向,边权非负, 航线:单向,边权可正可负,且无环. 根据题意,点可以分为很多团(连通块),团内部只有道路(道路是双向的,而且是连通的,所以不能存在航线,否 ...

  3. 揭开「拓扑排序」的神秘面纱

    作者 | 小齐本齐 责编 | Carol 来源 | 码农田小齐 Topological sort 又称 Topological order,这个名字有点迷惑性,因为拓扑排序并不是一个纯粹的排序算法,它 ...

  4. 腾讯在「无用」道路上越走越远

    杨净 发自 凹非寺 量子位 报道 | 公众号 QbitAI 真的还需要科学吗? 今年疫情如此席卷全球,科研本身展开挑战重重,科学交流更加困难. 科学,原本就是"贵族"的事情,少数人 ...

  5. OpenAI 以 10 亿美元出售「灵魂」,网友热评不再「Open」

    编译 | 禾木木 出品 | AI科技大本营(ID:rgznai100) OpenAI 如何以 10 亿美元的价格出售其灵魂:GPT-3 和 Codex 背后的公司并不像它声称的那样开放. 当金钱成为障 ...

  6. 马斯克:我有一个大胆的想法!给红绿灯加个AI视觉「外挂」

      转载自:视学算法   编辑:好困 [导读]大半夜的,四下无人又没车,为何还要我等这么久的红灯?这两天,马斯克也在思考这个问题. 对于社畜来说,大城市的交通无非分为两种: 白天不让上班:晚上不让回家 ...

  7. 3D建模复原汤加火山爆发!1000颗原子弹当量,人在英国刚被「震」到

      视学算法报道   编辑:好困 袁榭 [新智元导读]2022年汤加火山爆发,字面意义上震动了半个地球的人.从在家DIY树莓派套装监测震波的发烧友,到灾害科学家:从断网受灾的当地人,到刚找到的当地中国 ...

  8. 33个神经网络「炼丹」技巧

    点击上方"视学算法","星标"或"置顶" 关键时刻,第一时间送达 本文转载自:机器之心     作者:Andrej Karpathy 特斯拉 ...

  9. opengl实现3d点云_3D视觉CV界的终极体现形式,计算机如何「看」这个三维世界

    机器之心原创 作者:陈萍 打开手机进行人脸解锁:VR.AR 技术带来如此虚拟却真实的场景--3D 视觉几乎无所不能,在智能家居.智能安防.汽车电子.工业测量.新零售.智能物流等领域发挥重要作用,堪称赋 ...

最新文章

  1. 基于机器学习的捡球机器人设计与实现(探索)第2篇——7步完成opencv的安装(20190112)
  2. 1010. 一元多项式求导
  3. VTP (vlan trunking protocol)
  4. kafka再均衡监听器测试
  5. c++ map 多线程同时更新值 崩溃_深入理解并发安全的 sync.Map
  6. 《零基础》MySQL 教程(一)
  7. 程序员界年度人口普查:6成以上开发者日工作超9小时,且从不运动
  8. Element中 el-tag 点击事件 el-tag添加@click事件无效
  9. Java实验4 面向对象基础
  10. Day2 - Python基础2作业【购物车程序】
  11. [2018.07.10 T1]叠盒子
  12. 工具篇:Navicat-12版本破解安装
  13. 微信小程序 图片上传+php后台源码
  14. python成绩统计及格学平成_强化学习训练Chrome小恐龙Dino:最高超过4000分
  15. CoreAnimation动画入门(总结)
  16. 关于职业发展:一篇不错的文章分享
  17. 新浪小编为你介绍留声机的古与今
  18. 《数据结构(C语言版)》严巍敏课件~第一章:绪论
  19. Redis List命令大全
  20. 教你一招:安全打开U盘的方法

热门文章

  1. esxi管理端口_网工知识角|一分钟轻松了解华为端口安全机制
  2. python画蜡烛致敬烈士_「」matplotlib 股票-用python绘制蜡烛线型k线图是用代码还是绘图工具-TOP金融网...
  3. mysql connetor_python mysqlconnetor
  4. python+html语音人物交互_将HTML输入传递到python脚本
  5. 省选专练[POI2005]SAM-Toy Cars
  6. android编程常见问题- Resource ID #0x7f070001 type #0x12 is not valid
  7. pow(x,n) leecode
  8. 敏捷开发一千零一问系列之二:序言及解决问题的心法(无住)
  9. 【原创】简单轻松浏览FTP
  10. java 线程不足_Java 线程基础知识