从新开始,codeforces 567e

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 or 1 → 2 → 3 → 5 → 6.



题目大意是给你一个有向图以及一个起点,一个终点,从起点到终点走一条最短路,求对于每一条边,如果一定在最短路上输出YES,如果边权减去x后一定在最短路上,则输出can x,(边权减去x后要>0)如果无法一定在最短路上则输出NO。





这题显然首先一定要求出最短路mindis,同时我们可以发现对于每一条边(a,b),如果a到起点的距离加上b到终点的距离+1>=mindis,(这条边的距离最少减到1)就输出no,然后只剩下了输出can和yes的情况,我们考虑建一个最短路图,这样就满足了走最短路的条件,那么,从起点到终点是否一定经过某边就变成了求这个图的割边。用tarjan就行了


我看了一下出题人的做法,前面的部分与我基本一致,不过他判断一个点是否输出yes是这样判断的,他将s到t抽象成一个区间[1,n],这个区间上的点就是一条从s到t的路径,对于其他路径,你就做为另一个区间(l,r),覆盖原区间,那么,最后原区间没有被覆盖的区间就是必须经过的区间。



#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#define maxn 2010000
#define inf 0x7fffffff
using namespace std;
long long mindis=1LL*inf*inf;
struct fuck{
	typedef pair<long long,int> PII;
	//priority_queue<PII>q;
	priority_queue<PII,vector<PII>,greater<PII> >q;
	int pre[maxn],now[maxn],tot,son[maxn],val[maxn];
	void init(){
		memset(now,0,sizeof(now));
		tot=0;
	}
	void con(int a,int b,int c){
		pre[++tot]=now[a];
		now[a]=tot;
		son[tot]=b;
		val[tot]=c;
	}
	long long dis[maxn];
	void dij(int st,int ed){
		memset(dis,63,sizeof(dis));
		dis[st]=0;
		q.push(make_pair(0,st));
		do{
			PII x=q.top();q.pop();
			for(int p=now[x.second];p;p=pre[p])if(dis[son[p]]>dis[x.second]+val[p]){
				dis[son[p]]=dis[x.second]+val[p];
			//	printf("%d %d %d %d\n",st,ed,son[p],dis[son[p]]);
				q.push(make_pair(dis[son[p]],son[p]));
			}
		}while(!q.empty());
		mindis=min(mindis,dis[ed]);
	}
}z,f;
int dfn[maxn],num,low[maxn],fa[maxn];bool qiao[maxn],vis[maxn]; 
int a[maxn],b[maxn],c[maxn],n,m,s,t;
int pre[maxn],son[maxn],now[maxn],tot,val[maxn],no[maxn];
void con(int a,int b,int c,int d){
	pre[++tot]=now[a];
	now[a]=tot;
	son[tot]=b;
	val[tot]=c;
	no[tot]=d;
}
void tarjan(int x){
	vis[x]=1;
	dfn[x]=low[x]=++num;
	for(int p=now[x];p;p=pre[p])
	//	printf("%d %I64d %I64d %d %d\n",z.val[p],z.dis[x],f.dis[z.son[p]],x,z.son[p]);
	//		printf("x %d son %d %d %d\n",x,z.son[p],fa[x],p);
		if(!vis[son[p]]){
			fa[son[p]]=no[p];
			tarjan(son[p]);
			low[x]=min(low[x],low[son[p]]);
		}else if(fa[x]!=no[p])low[x]=min(dfn[son[p]],low[x]);
	if(x!=s&&fa[x]&&low[x]==dfn[x])qiao[fa[x]]=true;
//	printf("%d %d %d\n",x,low[x],dfn[x]);
} 

int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&a[i],&b[i],&c[i]);
		z.con(a[i],b[i],c[i]);f.con(b[i],a[i],c[i]);
	}
	z.dij(s,t);f.dij(t,s);
//	for(int i=1;i<=n;i++)printf("dis[%d]=%I64d %I64d\n",i,z.dis[i],f.dis[i]);
	for(int i=1;i<=m;i++){
		if(z.dis[a[i]]+f.dis[b[i]]+c[i]==mindis){
			con(a[i],b[i],c[i],i);
			con(b[i],a[i],c[i],i);
		}
	}
	tarjan(s);
	for(int i=1;i<=m;i++){
		if(qiao[i])puts("YES");
		else if(z.dis[a[i]]+f.dis[b[i]]+c[i]==mindis&&c[i]>1)puts("CAN 1");
		else if(z.dis[a[i]]+f.dis[b[i]]<mindis&&-z.dis[a[i]]-f.dis[b[i]]+mindis-1>0){
			//if(s==65669&&t==18384&&i==883)puts("fuck");
			printf("CAN %I64d\n",z.dis[a[i]]+f.dis[b[i]]+c[i]-mindis+1);
			//printf("fuck %I64d\n",-z.dis[a[i]]-f.dis[b[i]]+mindis-1);
		}
		else puts("NO");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值