191114-最优贸易(spfa)

191114-最优贸易

简化题意

本题是让我们在一张带节点权值的图上,找出一条从1到n的路径,使路径上能选出两个p,q(先经过点p,再经过点q),并且 a p − a q a_p-a_q apaq的值最大(a数组表示节点的权值)

解析

首先我们给这张图建一张反图,第一次在原图上跑spfa,求出节点1到各个节点所经过路径上最小点权值(记为 d i d_i di),然后在反图上跑一遍spfa,求出从节点n到各个节点所经过路径上最大点权值(记为 f i f_i fi),最后枚举每个点,计算 f i − d i f_i-d_i fidi的值,然后更新答案

题解

#include<bits/stdc++.h>
#define M 200008
using namespace std;
int nxt1[M*2],nxt2[M*2],first1[M],first2[M],to1[M*2],to2[M*2],d[M],f[M],n,m,ans,a[M],tot;
bool vis[M];
int read(){
	int f=1,re=0;
	char ch;
	for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
	if(ch=='-'){
		f=-1;
		ch=getchar();
	}
	for(;isdigit(ch);ch=getchar())
		re=(re<<3)+(re<<1)+ch-'0';
	return re*f;
}
void add1(int x,int y){
	nxt1[++tot]=first1[x];
	first1[x]=tot;
	to1[tot]=y;
}
void add2(int x,int y){
	nxt2[++tot]=first2[x];
	first2[x]=tot;
	to2[tot]=y;
}
void spfa_1(){
	queue<int>q;
	memset(d,127,sizeof(d));
	d[1]=a[1];
	q.push(1);
	vis[1]=1;
	while(q.size()){
		int v=q.front();
		q.pop();
		vis[v]=0;
		for(int i=first1[v];i;i=nxt1[i]){
			int u=to1[i];
			if(d[u]>min(d[v],a[u])){
				d[u]=min(d[v],a[u]);
				if(!vis[u]){
					q.push(u);
					vis[u]=1;
				}
			}
		}
	}
}
void spfa_2(){
	queue<int>q;
	memset(vis,0,sizeof(vis));
	f[n]=a[n];
	q.push(n);
	vis[n]=1;
	while(q.size()){
		int v=q.front();
		q.pop();
		vis[v]=0;
		for(int i=first2[v];i;i=nxt2[i]){
			int u=to2[i];
			if(f[u]<max(f[v],a[u])){
				f[u]=max(f[v],a[u]);
				if(!vis[u]) {
					q.push(u);
					vis[u]=1;
				}
			}
		}
	}
}
int main(){
	int x,y,z;
	n=read(),m=read();
	for(int i=1;i<=n;i++) a[i]=read();
	for(int j=1;j<=m;j++){
		x=read(),y=read(),z=read();
		if(z==1){
			add1(x,y);
			add2(y,x);
		}
		else{
			add1(y,x);
			add1(x,y);
			add2(x,y);
			add2(y,x);
		}
	}
	spfa_1();
	spfa_2();
	for(int i=1;i<=n;i++)
		ans=max(f[i]-d[i],ans);
	printf("%d",ans);
	return 0;
}

题外话

该题也可以用双向bfs做

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值