差分约束系统+spfa算法 poj1201

  先把问题转化为差分约束系统,然后把差分约束系统转化为满足条件的图,然后对图求最大(或者最小)路径。

 Dijkstral和Bell-man Ford是求单源最大最小路径的方法。但是效率并不高。

 spfa(shortest path fast algorithm)算法效率较高。因为,对于那些距离没变化的点v,以后也不可能通过v来使别的点u的路径发生变化。所以用一种记录的方式记录变化的点,没有变化的点就不予考虑了。这就比Dijkstral每次都检查所有的顶点或者Bell-man Ford都检查所有的边,检查n-1次效率要好。

做poj1201,第一次遇到这样的问题,我用很直观的贪心法去解。但是效率为O(n^2).

 然后花了很长时间琢磨差分约束系统为啥能转化为图的最短路径问题,然后看spfa算法的方法和实现。

 poj1201源代码:

/*
 * =====================================================================================
 *
 *       Filename:  1201.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2011年12月03日 10时32分51秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  MaZheng (blog.csdn.net/mazheng1989), mazheng19891019@gmail.com
 *        Company:  Dalian University Of Technology
 *
 * =====================================================================================
 */


#include<stdio.h>
#include<string.h>
#include<limits.h>
#include<queue>
using namespace std;
//please declare parameters here.
const int NUM=50005;
int n;
int low=INT_MAX,high=-1; //

struct Vertex
{
	int v;
	int w;
	Vertex *next;
};
Vertex * Graph[NUM];
int dis[NUM];
bool used[NUM];

//please declare functions here.
void addEdge(int u,int v,int w)
{

	Vertex *ver=new Vertex;
	ver->v=v;
	ver->w=w;
	ver->next=Graph[u];
	Graph[u]=ver;
}
void spfa()
{
   queue<int >Q;
   for(int i=low;i<=high;i++)
   {
	   dis[i]=-INT_MAX;
	   used[i]=false;
   }
   dis[low]=0;
   used[low]=true;
   Q.push(low);
   while(Q.empty()==false)
   {
	   int v=Q.front();
	   Q.pop();
	   used[v]=false;
	   Vertex *p=Graph[v];
	   while(p!=NULL)
	   {
		   int u=p->v;
		   if(dis[v]+p->w>dis[u])
		   {
			   dis[u]=dis[v]+p->w;
			   if(used[u]==false)
			   {
				   Q.push(u);
				   used[u]=true;
			   }
		   }
		   p=p->next;
	   }
   }
   printf("%d\n",dis[high]);
}
int main()
{
	freopen("input.txt","r",stdin);
	//input your ...
    int ai,bi,ci;
   	while(scanf("%d",&n)!=EOF)
	{
		low=INT_MAX;
		high=-1;
		memset(Graph,NULL,sizeof(Graph));
		for(int i=0;i<n;i++)
		{
			scanf("%d %d %d",&ai,&bi,&ci);
			if(ai<low)
				low=ai;
			if(bi+1>high)
				high=bi+1;
			addEdge(ai,bi+1,ci);
		}
		for(int i=low;i<=high;i++)
		{
			addEdge(i,i+1,0);
			addEdge(i+1,i,-1);
		}
		spfa();
	}

	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值