题意:给出一张有向图,每条边有长度,对于每条边,你要回答将该边的方向取反后,从起点到终点的最短距离是增加or减小or不变。

首先求出起点到所有点的最短距离和所有点到终点的最短距离(两次DIjkstra,第二次跑反向边即可),并建出最短路图。设ds[u]为起点到点u的最短距离,dt[u]为点u到终点的最短距离,对于每条边,设该边的两个端点u->v,以及边权c,分情况讨论:

若ds[v]+c+dt[u]>dt[s],此时将边取反后最短距离减小,否则需要判断该边是否为最短路图上s到t的割边,若是则最短距离增加,否则不变。

如何判断该边是否为s到t的割边?其实方法很简单,如果是割边,那么从s到t的所有路径都经过该边。由于最短路图是个DAG,设in[u]表示从起点走到u的路径数,out[v]表示从v走到终点的路径数,则每条边被通过的路径数=in[u]*out[v],只需判断in[u]*out[v]是否等于out[s]即可。注意这个路径数可能会很大甚至存不下,但由于只需要判断是否相等用哈希就可以,可以用unsigned long long溢出自动取模。

 #include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N=1e5+,inf=0x3f3f3f3f;
int n,m,hd[N],ne;
ll in[N],out[N],ds[N],dt[N],vis[N];
struct E {int u,v,c,nxt;} e[N<<];
void addedge(int u,int v,int c) {e[ne]= {u,v,c,hd[u]},hd[u]=ne++;}
struct D {
int u;
ll g;
bool operator<(const D& b)const {return g>b.g;}
};
priority_queue<D> q;
void upd(int u,ll ad,ll* dp) {
if(dp[u]>ad)dp[u]=ad,q.push({u,ad});
}
void dij() {
memset(ds,inf,sizeof ds);
while(q.size())q.pop();
upd(,,ds);
while(q.size()) {
int u=q.top().u;
ll g=q.top().g;
q.pop();
if(ds[u]!=g)continue;
for(int i=hd[u]; ~i; i=e[i].nxt)if(!(i&))upd(e[i].v,g+e[i].c,ds);
}
memset(dt,inf,sizeof dt);
while(q.size())q.pop();
upd(,,dt);
while(q.size()) {
int u=q.top().u;
ll g=q.top().g;
q.pop();
if(dt[u]!=g)continue;
for(int i=hd[u]; ~i; i=e[i].nxt)if(i&)upd(e[i].v,g+e[i].c,dt);
}
}
ll dfsin(int u) {
ll& ret=in[u];
if(vis[u])return ret;
vis[u]=,ret=;
if(u==)return ret=;
for(int i=hd[u]; ~i; i=e[i].nxt)if(i&) {
int v=e[i].v;
if(dt[u]+e[i].c!=dt[v])continue;
ret+=dfsin(v);
}
return ret;
}
ll dfsout(int u) {
ll& ret=out[u];
if(vis[u])return ret;
vis[u]=,ret=;
if(u==)return ret=;
for(int i=hd[u]; ~i; i=e[i].nxt)if(!(i&)) {
int v=e[i].v;
if(ds[u]+e[i].c!=ds[v])continue;
ret+=dfsout(v);
}
return ret;
}
int main() {
memset(hd,-,sizeof hd),ne=;
scanf("%d%d",&n,&m);
while(m--) {
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c);
addedge(v,u,c);
}
dij();
memset(vis,,sizeof vis);
for(int i=; i<=n; ++i)dfsin(i);
memset(vis,,sizeof vis);
for(int i=; i<=n; ++i)dfsout(i);
for(int i=; i<ne; i+=) {
int u=e[i].u,v=e[i].v;
if(dt[]>ds[v]+e[i].c+dt[u])puts("HAPPY");
else if(ds[u]+e[i].c==ds[v]&&in[u]*out[v]==out[])puts("SAD");
else puts("SOSO");
}
return ;
}

Aizu - 1383 Pizza Delivery (最短路图+DAG上的割边)的更多相关文章

  1. [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)

    [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...

  2. Vulnerable Kerbals CodeForces - 772C【拓展欧几里得建图+DAG上求最长路】

    根据拓展欧几里得对于同余方程 $ax+by=c$ ,有解的条件是 $(a,b)|c$. 那么对于构造的序列的数,前一个数 $a$  和后一个数 $b$ ,应该满足 $a*x=b(mod m)$ 即 $ ...

  3. Pizza Delivery

    Pizza Delivery 时间限制: 2 Sec  内存限制: 128 MB 题目描述 Alyssa is a college student, living in New Tsukuba Cit ...

  4. [NOIP2017]逛公园 最短路图 拓扑序DP

    ---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...

  5. 【暑假】[深入动态规划]UVa 1628 Pizza Delivery

    UVa 1628 Pizza Delivery 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51189 思路:    ...

  6. [HAOI2012]道路(最短路DAG上计数)

    C国有n座城市,城市之间通过m条[b]单向[/b]道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同.我们需要对每 ...

  7. 【NOIP2017】逛公园(最短路图,拓扑排序,计数DP)

    题意: 策策同学特别喜欢逛公园. 公园可以看成一张 N 个点 M 条边构成的有向图,且没有自环和重边.其中 1 号点是公园的入口, N 号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花 ...

  8. codeforces Gym 100338C Important Roads (重建最短路图)

    正反两次最短路用于判断边是不是最短路上的边,把最短路径上的边取出来建图.然后求割边.注意重边,和卡spfa. 正权,好好的dijkstra不用,用什么spfa? #include<bits/st ...

  9. Codeforces Round #545 (Div. 2) E 强连通块 + dag上求最大路径 + 将状态看成点建图

    https://codeforces.com/contest/1138/problem/E 题意 有n个城市(1e5),有m条单向边(1e5),每一周有d天(50),对于每个城市假如在某一天为1表示这 ...

随机推荐

  1. Unsupported major.minor version 52.0——解决

    Unsupported major.minor version 52.0 就是编辑用的是jdk8 而运行用的是jdk7, 改成jdk8就好了 参考文章:https://blog.csdn.net/qq ...

  2. Oracle的查询-分页查询

    --Oracle中的分页 --rownum行号:当我们做select操作时候 --每查询出一行记录,就在该行加上一个行号 --行号从1开始,一次递增,不能跳着走 ----emp表工资倒叙排列后,每页5 ...

  3. LeetCode-第 166 场周赛

    LeetCode-第 166 场周赛 1281.subtract-the-product-and-sum-of-digits-of-an-integer 1282.group-the-people-g ...

  4. MySQL中的InnoDB中产生的死锁深究

    查考地址:https://blog.csdn.net/loophome/article/details/79867174 待研究中.....

  5. 对Python中print函数参数的认识

    输出函数是最常用的,对print()参数的准确认识尤为重要. sep='':sep参数表示函数中不同value的分隔符,默认为一个空格. end='':end参数表示函数结尾的处理,默认换行. 例如: ...

  6. Java手写简单Linkedlist一(包括增加,插入,查找,toString,remove功能)

    @Java300 学习总结 一.自定义节点 LinkList底层为双向链表.特点为查询效率低,但增删效率高,线程不安全. 链表数据储存在节点,且每个节点有指向上个和下个节点的指针. 创建ggLinke ...

  7. tensorflow lite 之生成 tflite 模型文件

    下载最新的的tensorflow源码. 1.配置 tflite 文件转换所需环境 安装 bazel 编译工具 https://docs.bazel.build/versions/master/inst ...

  8. poj 2891 模数不互质的中国剩余定理

    Strange Way to Express Integers Description Elina is reading a book written by Rujia Liu, which intr ...

  9. c++11 常量表达式

    c++11 常量表达式 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inclu ...

  10. python selenium5 模拟点击+拖动+按照指定相对坐标拖动 58同城验证码

    #!/usr/bin/python # -*- coding: UTF-8 -*- # @Time : 2019年12月9日11:41:08 # @Author : shenghao/10347899 ...