[CF715B][最短路][构造]Complete The Graph

CF715B

考虑先把所有边填成1,这样不会影响最终答案,因为每条边都必须填一个正整数
接下来只需要在此基础上增大边权即可
我们先把填1的图做一遍dijkstra,然后再把原图做一遍dijkstra,第二次的时候如果遇到一条边 ( u , v ) (u,v) (u,v)没有权值,那就把边权设为 m a x ( 1 , L − d 2 [ u ] − d 1 [ v ] ) max(1,L-d2[u]-d1[v]) max(1,Ld2[u]d1[v]),其中 d 2 d2 d2表示当前最短路, d 1 d1 d1表示第一次跑出来的, v v v t t t的最短路,这样相当于确定了一条长为 L L L的最短路,并且由于我们每次改边权都确定了一条最短路,所以进行修改的边之间不会相互影响,则这样可以构造出答案
如果这样做完 s s s t t t的最短路仍然不等于 L L L则显然无解

Code:

#include<bits/stdc++.h>
#define mp make_pair
#define ll long long
#define fi first
#define se second
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
int L,s,t;
namespace Shortest_Path1{
	const int N=2e5+5;
	int vis[N],head[N],nxt[N],tot=0;ll d[N],c[N];
	inline void add(int x,int y,ll z){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;c[tot]=z;}
	int pt[N];
	inline void dijkstra(){
		priority_queue<pair<ll,int> >q;
		memset(d,0x3f,sizeof(d));
		memset(pt,0,sizeof(pt));
		d[t]=0;q.push(mp(0,t));
		while(!q.empty()){
			int x=q.top().se;q.pop();pt[x]=1;
			for(int i=head[x];i;i=nxt[i]){
				int y=vis[i],z=c[i];
				if(pt[y]) continue;
				if(z==0) z=1;
				if(d[y]>d[x]+z){
					d[y]=d[x]+z;
					q.push(mp(-d[y],y));
				}
			}
		}
	}
}
#define S1 Shortest_Path1
int ans[200005];
namespace Shortest_Path2{
	const int N=2e5+5;
	int vis[N],head[N],nxt[N],tot=0,id[N];
	ll c[N];
	inline void add(int x,int y,ll z,int w){vis[++tot]=y;id[tot]=w;nxt[tot]=head[x];head[x]=tot;c[tot]=z;}
	ll d[N];int pt[N];
	inline void dijkstra(){
		priority_queue<pair<ll,int> >q;
		memset(d,0x3f,sizeof(d));
		memset(pt,0,sizeof(pt));
		d[s]=0;q.push(mp(0,s));
		while(!q.empty()){
			int x=q.top().se;q.pop();pt[x]=1;
			for(int i=head[x];i;i=nxt[i]){
				int y=vis[i],z=c[i];
				if(pt[y]) continue;
				if(z==0) z=max(1ll,L-d[x]-S1::d[y]),ans[id[i]]=z;
				if(d[y]>d[x]+z){
					d[y]=d[x]+z;
					q.push(mp(-d[y],y));
				}
			}
		}
	}
}
#define S2 Shortest_Path2
int xx[200005],yy[200005];
int main(){
	int n=read(),m=read();L=read(),s=read()+1,t=read()+1;
	for(int i=1;i<=m;i++){
		int x=read()+1,y=read()+1,z=read();
		xx[i]=x-1,yy[i]=y-1;ans[i]=z;
		S1::add(x,y,z);S1::add(y,x,z);
		S2::add(x,y,z,i);S2::add(y,x,z,i);
	}
	S1::dijkstra();
	S2::dijkstra();
	if(S2::d[t]!=L) return puts("NO"),0;
	puts("YES");
	for(int i=1;i<=m;i++)
		cout<<xx[i]<<" "<<yy[i]<<" "<<ans[i]<<"\n";
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值