POJ 1860

AC这道题目不容易啊,看着蛮容易的,实则检测除了自己对最短路径算法的很多理解不到位之处。

第一:开始想这道题目的时候忽然对relaxing有了一种不熟悉的感觉,觉得relaxing对这道题目来说是不合适的,这道题目是求最大值,但是如果一个国家的汇率减去手续费变少了,后面一个国家就不会被更新了。我也不知道自己怎么想起来这个了。后来越想越不对,越想越觉得,这不是一道普通的求“最短路径”的问题,于是我奇葩的用变种的BFS来来做,这种做法,的确是我自己想出来的,想出来的时候还洋洋自得了。(其实是一个可以输出所有路径极其排列的算法....)但是跑样例的时候就是跑不对。后来一想,这种算法不会输出环,但是题中的答案是有环存在的,那么...这个题到底是什么妖怪?

就此卡住,然后回想,想了好久,终于忍不住去找结题报告,才发现,自己对松弛理解错了,更新的是后一个节点,后一个节点只和自己之前比较和前一个节点一点关系都没有,因此,如果有一条通往他的路径可以使原典到他的路径变短,他就会变短,因此,最短路径还是对的,而这道题目,也可以用最短路径的算法来做。

后来写BF算法的时候,又卡住了,最后终于想明白,是把边遍历N-1遍,是边而不是点,而且这个遍历不需要保存图的关系。另外,BF的出发点原点要 注意单独赋值,除了原点之外的都赋给无穷大(若求最大路径赋给无穷小),然后往小了松弛。

最后再松弛一遍边,那么就可以找到负环了(如果是找最大值就可以找到正环了)。

#include <iostream>

using namespace std;

struct c{
	int s;
	int e;
	double r;
	double m;
};

int main()
{
	int n,m,s;
	double dist[102];
	double v;
	int ts,te;
	c* edge[202];
	c* c1;
	c* c2;
	int i,j,k,en=0;
	cin>>n>>m>>s>>v;
	for(i=0;i<202;i++)
		edge[i]=NULL;
	for(i=0;i<102;i++)
		dist[i]=0;
	for(i=0;i<m;i++)
	{
		cin>>ts>>te;
		c1=new c;
		c1->s=ts;
		c1->e=te;
		cin>>c1->r>>c1->m;
		edge[en]=c1;
		en++;
		c2=new c;
		c2->s=te;
		c2->e=ts;
		cin>>c2->r>>c2->m;
		edge[en]=c2;
		en++;
	}
	dist[s]=v;
	for(i=0;i<n-1;i++)
	{
		for(j=0;edge[j]!=NULL;j++)
		{
			c1=edge[j];
			if(dist[c1->e]<(dist[c1->s]-c1->m)*c1->r)
				dist[c1->e]=(dist[c1->s]-c1->m)*c1->r;
		}
	}
	bool is=false;
	for(i=0;edge[i]!=NULL;i++)
	{		
		c1=edge[i];
		if(dist[c1->e]<(dist[c1->s]-c1->m)*c1->r)
		{
			cout<<"YES";
			is=true;
			return 0;
		}
	}
	if(!is)
	{
		cout<<"NO";
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值