最短路

因为有负权边,所以不能 dijkstra ,本题数据还卡 SPFA

但是我们发现,有负权的都是有向边,而且如果把无向边连成的联通块看成一个点的话,有向边就连成了一个 DAG,所以我们可以对所有的联通块用dij求最短路

在 DAG上用拓扑序求最短路

注意:

堆优化的 Dijkstra 在定义的结构体重载运算符的时候注意相反

因为存在负权边,所以两点不可达,不等价于两点间的距离 == inf ,应为 两点间的距离大于一个很大的数

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 100005;
int init() {
int rv = 0, fh = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') fh = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
rv = (rv<<1) + (rv<<3) + c - '0';
c = getchar();
}
return fh * rv;
}
int head[MAXN], n, m1, m2, s, nume, id[MAXN], tot, dis[MAXN], cnt[MAXN];
bool f[MAXN];
vector <int> ve[25005];
struct edge{
int to, nxt, dis;
}e[MAXN<<1];
void adde(int from, int to, int dis) {
e[++nume].to = to;
e[nume].nxt = head[from];
e[nume].dis = dis;
head[from] = nume;
}
void dfs(int u) {
if(id[u]) return;
id[u] = tot;
ve[tot].push_back(u);
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
dfs(v);
}
}
struct node{
int num, val;
bool operator < (const node & b) const{
return val > b.val;
}
};
priority_queue <node> q;
queue <int> qq;
void dij(int x){
for(int i = 0; i < (int)ve[x].size(); i++) q.push((node){ve[x][i], dis[ve[x][i]]});
while(!q.empty()) {
node u = q.top(); q.pop();
if(f[u.num]) continue;
f[u.num] = 1;
for(int i = head[u.num]; i; i = e[i].nxt) {
node v;
v.num = e[i].to;
if(id[v.num] == id[u.num] && dis[v.num] > dis[u.num] + e[i].dis) {
dis[v.num] = dis[u.num] + e[i].dis;
v.val = dis[v.num];
q.push(v);
}
if(id[v.num] != id[u.num]) {
dis[v.num] = min(dis[v.num], dis[u.num] + e[i].dis);
cnt[id[v.num]]--;
if(!cnt[id[v.num]]) {
qq.push(id[v.num]);
}
}
}
}
}
int main() {
n = init(); m1 = init(); m2 = init(); s = init();
for(int i = 1; i <= m1; i++) {
int u = init(), v = init(), di = init();
adde(u, v, di); adde(v, u, di);
}
for(int i = 1; i <= n; i++) {if(!id[i]) tot++;dfs(i);}
for(int i = 1; i <= m2; i++) {
int u = init(), v = init(), di = init();
adde(u, v, di);cnt[id[v]]++;
}
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
for(int i = 1; i <= tot; i++) if(!cnt[i]) qq.push(i);
while(!qq.empty()) {
int v = qq.front(); qq.pop();
dij(v);
}
for(int i = 1; i <= n; i++) {
if(dis[i] > 100000000) printf("NO PATH\n");
else printf("%d\n", dis[i]);
}
return 0;
}

最新文章

  1. 移动端 h5调试技巧
  2. OrcharNoCMS中的发布订阅使用
  3. java面试问题整理-垃圾回收
  4. 数据库的NULL值讨论
  5. Vrapper-Eclipse的vim插件安装方法
  6. angular的canvas画图例子
  7. HTML统一资源定位器
  8. Activator.CreateInstance 方法 (Type) 的用法
  9. XML参数转换为Object,并转换为List或DataTable
  10. Multiwii 代码解读
  11. 同一个ASP.NET页面放置多个UpdatePanel分别刷新的解决办法。.
  12. 鸟哥的linux私房菜学习-(二)VMware虚拟机及linux系统安装过程
  13. Python+Appium 查找 toast 方法的封装
  14. python学习day22 面向对象(四) 约束&amp;反射
  15. Unity中AB资源打包简单的脚本
  16. 【XSY2759】coin DP 线性插值
  17. Android7.0手机程序保活(附源码下载)
  18. python txt文件数据转excel
  19. 关于table动态添加数据 单元格合并 数组合并
  20. nginx Server names

热门文章

  1. Python——for表达式
  2. 主成分分析法(PCA)答疑
  3. linux之切换用户su(switch user)
  4. 如何在 JavaScript 中更好地使用数组
  5. PHP实现同array_column一样的功能
  6. vue组件:canvas实现图片涂鸦功能
  7. 【android】【android studio】修改emulator的本地化环境
  8. java 的多态(2013-10-11-163 写的日志迁移
  9. Geode 集群搭建,快速上手使用
  10. AND和OR