Codeforces E. President and Roads (优先队列Dijkstar + 强连通 找必最短路上的必须边(桥))经典

本文主要是介绍Codeforces E. President and Roads (优先队列Dijkstar + 强连通 找必最短路上的必须边(桥))经典,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

E. President and Roads
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Berland has n cities, the capital is located in city s, and the historic home town of the President is in city t (s ≠ t). The cities are connected by one-way roads, the travel time for each of the road is a positive integer.

Once a year the President visited his historic home town t, for which his motorcade passes along some path from s to t (he always returns on a personal plane). Since the president is a very busy man, he always chooses the path from s to t, along which he will travel the fastest.

The ministry of Roads and Railways wants to learn for each of the road: whether the President will definitely pass through it during his travels, and if not, whether it is possible to repair it so that it would definitely be included in the shortest path from the capital to the historic home town of the President. Obviously, the road can not be repaired so that the travel time on it was less than one. The ministry of Berland, like any other, is interested in maintaining the budget, so it wants to know the minimum cost of repairing the road. Also, it is very fond of accuracy, so it repairs the roads so that the travel time on them is always a positive integer.

Input

The first lines contain four integers nms and t (2 ≤ n ≤ 105; 1 ≤ m ≤ 105; 1 ≤ s, t ≤ n) — the number of cities and roads in Berland, the numbers of the capital and of the Presidents' home town (s ≠ t).

Next m lines contain the roads. Each road is given as a group of three integers ai, bi, li (1 ≤ ai, bi ≤ nai ≠ bi; 1 ≤ li ≤ 106) — the cities that are connected by the i-th road and the time needed to ride along it. The road is directed from city ai to city bi.

The cities are numbered from 1 to n. Each pair of cities can have multiple roads between them. It is guaranteed that there is a path froms to t along the roads.

Output

Print m lines. The i-th line should contain information about the i-th road (the roads are numbered in the order of appearance in the input).

If the president will definitely ride along it during his travels, the line must contain a single word "YES" (without the quotes).

Otherwise, if the i-th road can be repaired so that the travel time on it remains positive and then president will definitely ride along it, print space-separated word "CAN" (without the quotes), and the minimum cost of repairing.

If we can't make the road be such that president will definitely ride along it, print "NO" (without the quotes).

Sample test(s)
input
6 7 1 6
1 2 2
1 3 10
2 3 7
2 4 8
3 5 3
4 5 2
5 6 1
output
YES
CAN 2
CAN 1
CAN 1
CAN 1
CAN 1
YES
input
3 3 1 3
1 2 10
2 3 10
1 3 100
output
YES
YES
CAN 81
input
2 2 1 2
1 2 1
1 2 2
output
YES
NO
Note

The cost of repairing the road is the difference between the time needed to ride along it before and after the repairing.

In the first sample president initially may choose one of the two following ways for a ride: 1 → 2 → 4 → 5 → 6 or1 → 2 → 3 → 5 → 6.

题意 : 给 n<=10^5 个点 m <=10^5  条带权(即时间 1<=t<=10^6)边的有向图 (有重边), 现在要从起点VS 到终点 VT ,走的是最短时间。输出 m 行,如果第 i 行输出的是YES 表示 第 i  条边 是最短路的必经路。如果输出的是 CAN x  ,则表示 修改 第 i  条边(第 i 条边的边权 减少了 x )使得原来的最短路减少1,必经过这条边。如果输出 NO 表示无法修改减少边权 使得最短路减少 1 。修改边的原则是:修改后的边权>0。

解题: 先用优先队列优化Dijkstar(用spfa超时),求起点vs到每个点的最短时间 time1[],再求从终点vt 反向图到每个点的最短时间 time2[] 。现在要判断必经路:重新建一个无向图,图中的边都是属于求出的最短路上的有边。用 强连通 判断桥(即必经路也是必须路),因为断了桥图就变成了两个连通块,所以桥即必经路。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
using namespace std;
#define ll __int64
const int N = 100005;
const ll INF = (ll)999999999999;
struct nnn
{int u,v;ll t;
}node[N];struct EDG{int to,next;ll t;
}edg[N*3];struct NNNN{int u;ll t;friend bool operator<(NNNN aa , NNNN bb){return aa.t>bb.t;}
};int eid,head[N] , vs , vt , n ;
ll time1[N],time2[N]; //从 vs 到每个点的最短时间 和 从 vt 反向到每个点的最短时间
bool inq[N];
void init()
{eid=0;memset(head,-1,sizeof(head));
}
void addEdg(int u ,int v,ll t,ll tt=0)
{edg[eid].to=v; edg[eid].next=head[u];edg[eid].t=t; head[u]=eid++;edg[eid].to=u; edg[eid].next=head[v];edg[eid].t=tt; head[v]=eid++;
}
void dijstar(int flag)
{priority_queue<NNNN>q;NNNN now , pre;int u,v;for(int i=1; i<=n; i++){if(flag==0) time1[i]=INF;  else   time2[i]=INF;inq[i]=0;}now.t = 0;if(flag==0)time1[vs]=0 , now.u = vs;elsetime2[vt]=0 , now.u = vt;q.push(now);while(!q.empty()){pre=q.top(); q.pop();u=pre.u;if(inq[u]) continue;inq[u]=1;for(int i=head[u]; i!=-1; i=edg[i].next){v=edg[i].to;if(inq[v])continue;if(flag==0){if(time1[v]>time1[u]+edg[i].t&&edg[i].t!=INF){time1[v]=time1[u]+edg[i].t;now.t = time1[v] ;now.u = v;q.push(now);}}else{ //反向求最短时间int ti=i^1;if(time2[v]>time2[u]+edg[ti].t&&edg[i].t==INF){time2[v]=time2[u]+edg[ti].t;now.t = time2[v] ;now.u = v;q.push(now);}}}}
}bool ok[N] , vistedg[N];
int low[N] , dfn[N] , deep ;
void tarjar(int u )
{low[u] = dfn[u] = ++deep;for(int i=head[u] ; i!=-1; i=edg[i].next){int v=edg[i].to ;if(vistedg[edg[i].t]){ //有重边找必经路,只能用标记边的办法才会正确,不用 v==f head[u] = edg[i].next; continue;}head[u] = edg[i].next; //每条边只用一次vistedg[edg[i].t] = 1;if( !dfn[v] ){tarjar( v ) ;low[u] = low[u] < low[v] ? low[u] : low[v] ;if(dfn[u] < low[v]) ok[edg[i].t]=1;  //桥,则是必经路}else if(low[u]>dfn[v])low[u] = dfn[v] ;}
}
int main()
{int m , u , v ;ll t;while(scanf("%d%d%d%d",&n,&m,&vs,&vt)>0){init();for(int i=0; i<m; i++){scanf("%d%d%I64d",&u,&v,&t);node[i].u=u;node[i].v=v;node[i].t=t;addEdg(u , v , t , INF);}dijstar(0);dijstar(1);ll shorttime=time1[vt];deep=0;init();memset(ok , 0 , sizeof( ok ));memset(dfn , 0 , sizeof( dfn ));memset(vistedg , 0 , sizeof( vistedg ));for(int i=0; i<m; i++){ //重新建一个只有在最短路上的边的无向图,只用于找必须边,也就是找 桥 u=node[i].u;v=node[i].v;if(time1[u]+node[i].t+time2[v]==shorttime)addEdg(u,v,i,i) ;}tarjar( vs ) ;for(int i=0; i<m; i++)if(ok[i])printf("YES\n");else {u=node[i].u;v=node[i].v;t=shorttime-time1[u]-time2[v]-1; if(t>0)printf("CAN %I64d\n",node[i].t-t);elseprintf("NO\n");}}
}

 

这篇关于Codeforces E. President and Roads (优先队列Dijkstar + 强连通 找必最短路上的必须边(桥))经典的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983630

相关文章

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi