洛谷P10110 [GESP202312 七级] 商品交易

题目

传送门

题意

给定你n种商品和他们的价值,要你在M个商人的交易中,用你持有的商品a获得你希望获得的商品b,并且求最小花费,找不到输出No solution,并且我们观察样例可以发现有负边权

思路

毫无疑问,这个一眼就是最短路。由于有负边权,所以我们可以用SPFA

难点

边的权值,例如x可以置换y那么我们边的权值为a[y]-a[x]+1,这里加一是手续费

代码

有注释版

#include<bits/stdc++.h>
using namespace std;
struct edge{
	long long from,to,len,next;
}; 
long long n,e,k,qs,zd;
edge a[200005];
long long p[100005];
long long d[100005];
long long d1[100005];
queue<long long> q;
bool f[20010];
void add(int x,int y){
	k++;
	a[k].from=x;
	a[k].to=y;
	a[k].len=d1[y]-d1[x]+1;//刚刚的难点 
	a[k].next=p[x];//邻接表 
	p[x]=k;//邻接表 
}
void spfa(){
	memset(d,0x3f3f,sizeof(d));
	d[qs]=0;//初始化启始点 
	q.push(qs);//同理 
	f[qs]=true;//同理 
	while(q.size()!=0){
		int h=q.front();
		for(int i=p[h];i!=0;i=a[i].next){//遍历可以去的边 
			int to=a[i].to;
			if(d[h]+a[i].len<d[to]){//如果更优 
				d[to]=d[h]+a[i].len;//替代 
				if(f[to]==0){//说明y点不在队列 
					q.push(to);//入队 
					f[to]=true; //标记 
				}
			}
		}
		f[h]=false;//出队标记 
		q.pop(); 
	} 
}
int main(){
	std::ios::sync_with_stdio(false);//关闭输入输出流 
	std::cin.tie(0);
	std::cout.tie(0);
	cin>>n>>e>>qs>>zd;
	for(int i=0;i<n;i++){
		cin>>d1[i];
	}
	for(int i=1;i<=e;i++){
		int x,y;
		cin>>x>>y;
		add(x,y);//建图 
	}
	spfa();
	if(d[zd]>=0x3f3f)cout<<"No solution";//不能找到 
	else  cout<<d[zd];
	return 0;
} 

无注释版

#include<bits/stdc++.h>
using namespace std;
struct edge{
	long long from,to,len,next;
}; 
long long n,e,k,qs,zd;
edge a[200005];
long long p[100005];
long long d[100005];
long long d1[100005];
queue<long long> q;
bool f[20010];
void add(int x,int y){
	k++;
	a[k].from=x;
	a[k].to=y;
	a[k].len=d1[y]-d1[x]+1;
	a[k].next=p[x];
	p[x]=k;
}
void spfa(){
	memset(d,0x3f3f,sizeof(d));
	d[qs]=0;
	q.push(qs);
	f[qs]=true;
	while(q.size()!=0){
		int h=q.front();
		for(int i=p[h];i!=0;i=a[i].next){
			int to=a[i].to;
			if(d[h]+a[i].len<d[to]){
				d[to]=d[h]+a[i].len;
				if(f[to]==0){
					q.push(to);
					f[to]=true; 
				}
			}
		}
		f[h]=false;
		q.pop(); 
	} 
}
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);
	cin>>n>>e>>qs>>zd;
	for(int i=0;i<n;i++){
		cin>>d1[i];
	}
	for(int i=1;i<=e;i++){
		int x,y;
		cin>>x>>y;
		add(x,y);
	}
	spfa();
	if(d[zd]>=0x3f3f)cout<<"No solution";
	else  cout<<d[zd];
	return 0;
} 

一道SPFA的模板题

posted @ 2026-08-22 00:37  陈晨2011  阅读(7)  评论(0)    收藏  举报