博客
关于我
P1073 最优贸易(SPFA)
阅读量:394 次
发布时间:2019-03-05

本文共 2335 字,大约阅读时间需要 7 分钟。

最优贸易

NOIP 2009 提高组 第三题

题目大意

有n个点,有m个通道(有向或无向)。他要找到一条路,点可以重复出现。在路上,买水晶球再卖掉水晶球,最后到n点。要求出他最大能赚多少钱(用卖水晶球的钱减买水晶球的钱
分析
复杂的分析
在这里插入图片描述下面深入理解
可以用两个spfa算法
邻接表建立,如图:
在这里插入图片描述从1点去找,找到能到的点,并且赋值给他们:买水晶球最小的钱

void spfa1(int o){   	minn[o]=w[o];//初值    head=0;tail=1;	b[1]=o;c[o]=1;    do    {           head=head%N+1;//循环队列,否则会炸        int k=b[head];//方便        for(int i=head1[k];i;i=a1[i].next)         if(minn[a1[i].to]>min(minn[k],w[a1[i].to]))//松弛算法          {               minn[a1[i].to]=min(minn[k],w[a1[i].to]);            if(c[a1[i].to]==0)//是否标记过,没有就将这个数进入队列             {               	tail++;            	b[tail]=a1[i].to;            	c[a1[i].to]=1;             }          }    	c[k]=0;    }while(head

下面的需要将邻接表倒置,如图

在这里插入图片描述
从n点去找,找到能到的点,并且赋值给他们:卖水晶球最大的钱

void spfa2(int o){   	maxn[o]=w[o];//初值    head=0;tail=1;	b[1]=o;c[o]=1;    do    {           head=head%N+1;//循环队列,否则炸        int k=b[head];//方便        for(int i=head2[k];i;i=a2[i].next)         if(maxn[a2[i].to]

注意:复制后要仔细修改一些细节

最后,从2点到(n-1)点进行枚举,找到同一个点,让它的卖水晶球减卖水晶球的钱最多(不包括起点和终点)

for(int i=2;i<=n-1;i++)//找最大赚的钱	 m=max(m,maxn[i]-minn[i]);

这个点得出的值就是结果

AC代码

#include
using namespace std;#define N 1000005#define M 5000005int n,m,x,y,z,tot1,tot2,head,tail,b[M],c[N],w[N],head1[M],head2[M],maxn[N],minn[N];struct stu{ int to,next,w;}a1[M],a2[M];void add1(int x,int y)//邻接表1号{ tot1++; a1[tot1].to=y; a1[tot1].next=head1[x]; head1[x]=tot1;}void add2(int x,int y)//邻接表2号(要倒置){ tot2++; a2[tot2].to=y; a2[tot2].next=head2[x]; head2[x]=tot2;}void spfa1(int o){ minn[o]=w[o];//初值 head=0;tail=1; b[1]=o;c[o]=1; do { head=head%N+1;//循环队列,否则会炸 int k=b[head];//方便 for(int i=head1[k];i;i=a1[i].next) if(minn[a1[i].to]>min(minn[k],w[a1[i].to]))//松弛算法 { minn[a1[i].to]=min(minn[k],w[a1[i].to]); if(c[a1[i].to]==0)//是否标记过,没有就将这个数进入队列 { tail++; b[tail]=a1[i].to; c[a1[i].to]=1; } } c[k]=0; }while(head
>n>>m; for(int i=1;i<=n;i++) { cin>>w[i];//每个地方的买和卖水晶球的钱 minn[i]=2147483647;//赋大值 } for(int i=1;i<=m;i++) { cin>>x>>y>>z; add1(x,y); add2(y,x); if(z==2)add1(y,x);//双向 if(z==2)add2(x,y);//双向 } spfa1(1); for(int i=1;i<=n;i++)//清零 c[i]=0; spfa2(n); m=0; for(int i=2;i<=n-1;i++)//找最大赚的钱 m=max(m,maxn[i]-minn[i]); cout<

谢谢

转载地址:http://tqpzz.baihongyu.com/

你可能感兴趣的文章
Mysql学习总结(36)——Mysql查询优化
查看>>
Mysql学习总结(37)——Mysql Limit 分页查询优化
查看>>
Mysql学习总结(38)——21条MySql性能优化经验
查看>>
Mysql学习总结(39)——49条MySql语句优化技巧
查看>>
Mysql学习总结(3)——MySql语句大全:创建、授权、查询、修改等
查看>>
Mysql学习总结(40)——MySql之Select用法汇总
查看>>
Mysql学习总结(41)——MySql数据库基本语句再体会
查看>>
Mysql学习总结(42)——MySql常用脚本大全
查看>>
Mysql学习总结(43)——MySQL主从复制详细配置
查看>>
Mysql学习总结(44)——Linux下如何实现mysql数据库每天自动备份定时备份
查看>>
Mysql学习总结(45)——Mysql视图和事务
查看>>
Mysql学习总结(46)——8种常被忽视的SQL错误用法
查看>>
Mysql学习总结(48)——MySql的日志与备份还原
查看>>
Mysql学习总结(49)——从开发规范、选型、拆分到减压
查看>>
Mysql学习总结(4)——MySql基础知识、存储引擎与常用数据类型
查看>>
Mysql学习总结(50)——Oracle,mysql和SQL Server的区别
查看>>
Mysql学习总结(51)——Linux主机Mysql数据库自动备份
查看>>
Mysql学习总结(52)——最全面的MySQL 索引详解
查看>>
Mysql学习总结(53)——使用MySql开发的Java开发者规范
查看>>
Mysql学习总结(54)——MySQL 集群常用的几种高可用架构方案
查看>>