先把问题转化为差分约束系统,然后把差分约束系统转化为满足条件的图,然后对图求最大(或者最小)路径。
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;
}