题意:给出一张有向图,每条边有长度,对于每条边,你要回答将该边的方向取反后,从起点到终点的最短距离是增加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. 前端ajax中运用post请求和get请求之于session验证

    首先我们来看下ajax两种请求的区别: Ajax中POST和GET的区别Get和Post都是向服务器发送的一种请求,只是发送机制不同. 1. GET请求会将参数跟在URL后进行传递,而POST请求则是 ...

  2. js 跳转传递汉字参数

    父界面: myChart.on('click', function (params) { var dataIndex = params.dataIndex; if(params.name != &qu ...

  3. jq+js获取到table标签中的value

    前端jsp页面,(这里接收后端的参数方式没有放在上面) <table> <tbody id="fPzQwQwzbrList"> <tr id=&quo ...

  4. Python+request超时和重试

    Python+request超时和重试 一.什么是超时? 1.连接超时 连接超时指的是没连接上,超过指定的时间内都没有连接上,这就是连接超时.(连接时间就是httpclient发送请求的地方开始到连接 ...

  5. 分享 Shiro 学习过程中遇到的一些问题

    最近在学习 shiro 安全框架后,自己手写了一个小的管理系统 web 项目,并使用 shiro 作为安全管理框架.接下来分享一下在这过程中,遇到的一些问题以及自己的解决思路和方法. 一.Log ou ...

  6. Ural 1298 Knight 题解

    目录 Ural 1298 Knight 题解 题意 题解 程序 Ural 1298 Knight 题解 题意 给定一个\(n\times n(1\le n\le8)\)的国际象棋棋盘和一个骑士(基本上 ...

  7. 数据结构C++实现-第一章 绪论

    1.1 计算机与算法 1.1.3 起泡排序 void bubbleSort(int a[], int n) { for(bool sorted=false; !sorted; --n) { sorte ...

  8. Python学习笔记:格式化输出

    %d digit%s string%f float程序运用:name = input("please input your name:")age = int(input(" ...

  9. Java 字符串比较

    1.字符串比较 compareTo() 方法用于两种方式的比较: 字符串与对象进行比较. 按字典顺序比较两个字符串. 返回值 返回值是整型,它是先比较对应字符的大小(ASCII码顺序),如果第一个字符 ...

  10. poj 1753高斯

    和前面的开关问题差不多,就是要理解一下我们方程等号的右端代表的含义是什么.我们建立的方程是想让对位的位置变或者不变,然后生成增广矩阵的时候要多注意一点. ac代码: #include #include ...