2019ICPC(银川) - Delivery Route(强连通分量 + 拓扑排序 + dijkstra)
题目:有n个派送点,x条双向边,y条单向边,出发点是s,双向边的权值均为正,单向边的权值可以为负数,对于单向边给出了一个限制:如果u->v成立,则v->u一定不成立。问,从s出发,到其他所有点的最短路是多少(包括s)。
思路:对于单向边的限制,我们可以这么理解:双向边相连接的点一定组成一个强连通分量,如果一条单向边存在于某个强连通分量中,可以得出:如果“u -> v”,则一定“v -> u”,可以推出单向边一定只存在于连接两个强连通分量,且还可以推出,强连通分量缩点后,连上单向边,此时的图一定是一个有向无环图,于是给出的限制"对于单向边给出了一个限制:如果u->v成立,则v->u一定不成立。"完全成立,于是图的性质我们分析完了。
①似乎这个图的性质可以直接跑dijkstra,的确可以,但是负权边的存在复杂度太大。
②每个强连通分量都可以dijkstra,且图存在拓扑排序,不如让入度为0的缩点先跑dijkstra,然后一条单向边只影响其他强连通分量的一个点的距离,然后按照拓扑序来确定每个强连通分量跑dijkstra的顺序。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue> #define ll long long
#define pb push_back
#define fi first
#define se second using namespace std; const int N = + ;
const int M = + ;
const ll INF = 1e10;
struct Edge{
int to, nxt, w;
}e[M << ];
struct node{
int u, v, w;
};
struct tmp{
int now;
ll w;
bool friend operator<(const tmp& a, const tmp& b){
return a.w > b.w;
}
};
int head[N], scc[N], du[N], vis[N], ok[N];
ll dis[N];
vector<node > vp[N];//单向边
vector<int > belong[N];//属于哪个scc
vector<int > mp[N];//存边
priority_queue<tmp > pque;
int n, x, y, s, tot, col; inline void add(int u, int v, int w){
e[tot].to = v; e[tot].nxt = head[u];
e[tot].w = w; head[u] = tot++;
} //缩点
void dfs(int now){
scc[now] = col;
belong[col].pb(now);
for(int o = head[now]; ~o; o = e[o].nxt)
if(!scc[e[o].to]) dfs(e[o].to);
} //检测这个点是不是有效点
void check(int now){
ok[now] = ;
for(auto to : mp[now])
if(!ok[to]) check(to);
} void dijkstra(int ss){
while(!pque.empty()) pque.pop();
if(ss == s) pque.push({ss, dis[ss]}); //图一定是从出发点s开始的
else{
//相当于从一个超级源点出发
for(auto it : belong[scc[ss]]) pque.push({it, dis[it]});
}
while(!pque.empty()){
int u = pque.top().now;
pque.pop();
if(vis[u]) continue;
vis[u] = ;
for(int o = head[u]; ~o; o = e[o].nxt){
if(dis[u] + e[o].w < dis[e[o].to]){
dis[e[o].to] = dis[u] + e[o].w;
pque.push({e[o].to, dis[e[o].to]});
}
}
}
} void top_sort(){
queue<int > que;
que.push(scc[s]);//满足的图 应该是从s的连通图出发的拓扑图
dijkstra(s);
while(!que.empty()){
int inx = que.front();
que.pop();
for(auto it : vp[inx]){
//一条单向边影响一个点的距离
if(dis[it.u] + it.w < dis[it.v]){
dis[it.v] = dis[it.u] + it.w;
}
//入度0,跑dijkstra
if(--du[scc[it.v]] == ){
que.push(scc[it.v]);
dijkstra(it.v);
}
}
}
} void solve(){
scanf("%d%d%d%d", &n, &x, &y, &s);
for(int i = ; i <= n; ++i) head[i] = -; tot = ;
for(int i = ; i <= n; ++i) dis[i] = INF; dis[s] = ;
int u, v, w;
for(int i = ; i <= x; ++i){
scanf("%d%d%d", &u, &v, &w);
add(u, v, w); add(v, u, w);
mp[u].pb(v); mp[v].pb(u);
} vector<node > tmp;
for(int i = ; i <= y; ++i){
scanf("%d%d%d", &u, &v, &w);
tmp.pb({u, v, w});
mp[u].pb(v);
}
//图一定是从出发点s开始的,所以从s出发遍历图,无法到达的点,就是无法到达的点
//检测这个点是不是有效点
check(s);
//缩点
for(int i = ; i <= n; ++i){
if(!scc[i] && ok[i]){
++col;
dfs(i);
}
}
//入度统计
for(auto x : tmp){
if(ok[x.u] && ok[x.v]){//有效点
vp[scc[x.u]].pb(x);
++du[scc[x.v]];
}
}
top_sort();//拓扑序
for(int i = ; i <= n; ++i){
if(dis[i] == INF) printf("NO PATH\n");
else printf("%lld\n", dis[i]);
}
} int main(){ solve(); return ;
} /*
7 5 3 4
1 2 5
3 4 5
5 6 10
5 7 4
6 7 105
3 5 -100
4 6 -100
7 2 -100
*/
2019ICPC(银川) - Delivery Route(强连通分量 + 拓扑排序 + dijkstra)的更多相关文章
- BZOJ_3887_[Usaco2015 Jan]Grass Cownoisseur_强连通分量+拓扑排序+DP
BZOJ_3887_[Usaco2015 Jan]Grass Cownoisseur_强连通分量+拓扑排序+DP Description In an effort to better manage t ...
- BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset
BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i ...
- poj 2762(强连通分量+拓扑排序)
题目链接:http://poj.org/problem?id=2762 题意:给出一个有向图,判断任意的两个顶点(u,v)能否从u到达v,或v到达u,即单连通,输出Yes或No. 分析:对于同一个强连 ...
- BZOJ1924:[SDOI2010]所驼门王的宝藏(强连通分量,拓扑排序)
Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室 ...
- CDOJ 图论专题 A.不是图论 强连通分量+拓扑排序 经典
题目链接 在其中纠错第一次wa代码 #include <cstdio> #include <cstring> #include <cstdlib> #includ ...
- POJ 2762 Going from u to v or from v to u?(强连通分量+拓扑排序)
职务地址:id=2762">POJ 2762 先缩小点.进而推断网络拓扑结构是否每个号码1(排序我是想不出来这点的. .. ).由于假如有一层为2的话,那么从此之后这两个岔路的点就不可 ...
- hihoCoder #1185 : 连通性·三(强联通分量+拓扑排序)
#1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...
- POJ-2762-Going from u to v or from v to u(强连通, 拓扑排序)
链接: https://vjudge.net/problem/POJ-2762 题意: In order to make their sons brave, Jiajia and Wind take ...
- poj 2186 "Popular Cows"(强连通分量入门题)
传送门 参考资料: [1]:挑战程序设计竞赛 题意: 每头牛都想成为牛群中的红人. 给定N头牛的牛群和M个有序对(A, B),(A, B)表示牛A认为牛B是红人: 该关系具有传递性,所以如果牛A认为牛 ...
随机推荐
- 前端每日实战:85# 视频演示如何用纯 CSS 创作一个小球反弹的动画
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/OwWROO 可交互视频 此视频是可 ...
- Core + Vue 后台管理基础框架0——开篇
1.背景 最近,打算新开个项目,鉴于团队技术栈,选型.net core + vue,前后端分离.本打算捡现成的轮子的,github上大致逛了逛,总发现这样那样的不太适合心中那些“完美实践”,例如:Ab ...
- Sequence to Sequence Learning with Neural Networks论文阅读
论文下载 作者(三位Google大佬)一开始提出DNN的缺点,DNN不能用于将序列映射到序列.此论文以机器翻译为例,核心模型是长短期记忆神经网络(LSTM),首先通过一个多层的LSTM将输入的语言序列 ...
- 基于GIS空间分析的多边形提取技术
现有基于矢量图形的骨架线提取方法主要包括数据预处理.基于约束 Delauny 三角剖分的骨架线结点生成和骨架线的连接 3 个过程,上述过程都可利用现有 GIS 系统的数据处理.空间分析和建模功能实现. ...
- web测试喜事连连--草稿箱功能
“草稿箱”功能很常见吧,编辑内容后,不想发布的话,就先存为草稿.啥时候想公开了,发布即可. 今天发生个啥事呢,让作为Tester的我,哭笑不得. 开发部经理老F,反馈一个客户需求,发到群里让大家讨论. ...
- python基础学习day03
基础数据类型总览 why:机器无法像人一样分编各种类型 int(数字) str(字符串)作用:存储少量信息. '12','我和你','qw' bool值 作用:判断真假 True False list ...
- 聊一聊React中虚拟DOM
1. 什么是虚拟 DOM 在 React 中实际上是 render 函数中return 的内容会生成 DOM,return 中的内容由两部分组成,一部分是 JSX ,另一部分就是 state 中的数据 ...
- Android位置服务开发
1. 使用LocationManager获取地理位置信息 代码如下: private TextView positiontext; private String provider; private L ...
- 大数据软件安装之Flume(日志采集)
一.安装地址 1) Flume官网地址 http://flume.apache.org/ 2)文档查看地址 http://flume.apache.org/FlumeUserGuide.html 3) ...
- sleep()和wait()方法的区别
1,sleep()声明在Thread类中,而且是静态方法: wait()声明在Object类中,而且必须由锁对象调用. 2,sleep()时间达到后恢复: wait()可以设置事件自动恢复,如果没有设 ...