最优贸易题解

题目链接
感觉这道题只要知道spfa算法可以枚举沿途最大点和最小点,正向和反向建图,两遍spfa即可。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define maxn 500010
ll n,m,cnt1,cnt2,ans;ll head1[maxn],head2[maxn]; 
ll dis1[maxn],dis2[maxn];ll vis1[maxn],vis2[maxn];
ll val[maxn];
ll aa,bb,opt;
struct node{
	ll y,next;
}ed1[maxn],ed2[maxn];
queue<int>q1;queue<int>q2;

void add1(ll xx,ll yy){//正向建图 
	++cnt1;
	ed1[cnt1].y=yy;
	ed1[cnt1].next=head1[xx];
	head1[xx]=cnt1;
}

void add2(ll xx,ll yy){//反向建图 
	++cnt2;
	ed2[cnt2].y=yy;
	ed2[cnt2].next=head2[xx];
	head2[xx]=cnt2;
}

void spfa1(){//找的是最小的 
	memset(dis1,0x3f,sizeof(dis1));
	memset(vis1,0,sizeof(vis1));
	vis1[1]=1;q1.push(1);dis1[1]=val[1];
	while(!q1.empty()){
		ll x=q1.front();q1.pop();
		vis1[x]=0;
		for(int i=head1[x];i;i=ed1[i].next){
			ll vv=ed1[i].y;
			if(dis1[x]<dis1[vv]){
				dis1[vv]=min(dis1[x],val[vv]);
				if(!vis1[vv]){
					vis1[vv]=1;q1.push(vv);
				}
			}
		}
	}
} 

void spfa2(){//找的是最大的 
	memset(dis2,0,sizeof(dis2));
	memset(vis2,0,sizeof(vis2));
    vis2[n]=1;q2.push(n);dis2[n]=val[n];
	while(!q2.empty()){
		int x=q2.front();q2.pop();
		vis2[x]=0;
		for(int i=head2[x];i;i=ed2[i].next){
			ll vv=ed2[i].y;
			if(dis2[x]>dis2[vv]){
				dis2[vv]=max(dis2[x],val[vv]);
				if(!vis2[vv]){
					vis2[vv]=1;q2.push(vv);
				}
			}
		}
	}
} 

int main(){
	cin>>n>>m;
	for(int i=1;i<=n;++i)cin>>val[i];
//	for(int i=1;i<=n;++i){dis1[i]=dis2[i]=val[i];}
	for(int i=1;i<=m;++i){
		cin>>aa>>bb>>opt;
		add1(aa,bb);add2(bb,aa);
		if(opt==2)add1(bb,aa),add2(aa,bb);
	}
	spfa1();spfa2();
	for(int i=1;i<=n;++i){
//		printf("%lld %lld\n",dis1[i],dis2[i]);
		ans=max(ans,dis2[i]-dis1[i]); 
	}
	printf("%lld\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值