刚学了差分约束系统。
差分约束就是给你一堆不等式,求一个满足条件的解。比如x-y>=z,x-y<=z这些。对于大于等于的,我们可以转化为从y到x的单向最长路径,小于等于的则是最短路径。我们还要努力找到题目中的隐藏条件,或者自己建立一个原点什么的,这样才可以做。要注意的是,差分约束系统中通常会出现负数,也就是转化后变成负边权,所以不可以用Dijkstra,那我们就用SPFA就好了。
POJ1201为模板题。
#include <cstdio>
#include <cstring>
#define MS(a,b) memset(a,b,sizeof(a))
#define FOR(i,x,y) for(int i=x;i<=y;++i)
const int o=50010;
int ans,st,en,n,m,a,b,c,k,head,tail,itr,map1[o],dis[o],point[o];
bool vis[o];
struct EDGE//邻接表
{
int v,w,next;
}edge[o*3];
void addedge(int s,int v,int w)
{
edge[itr].v=v;
edge[itr].w=w;
edge[itr].next=map1[s];
map1[s]=itr++;
}
int spfa(int st,int en)
{
FOR(i,st,en) dis[i]=0xc0c0c0c0;//表示与起点的距离
dis[st]=0; point[1]=st; head=1; tail=0; vis[st]=true;//队列准备
while(tail!=head)
{
tail=(tail+1)%o;//循环队列
k=point[tail];
vis[k]=false;//该地点用过后出队
for(int i=map1[k];i!=-1;i=edge[i].next) if(dis[edge[i].v]<dis[k]+edge[i].w)//最短路
{
dis[edge[i].v]=dis[k]+edge[i].w;
if(!vis[edge[i].v])
{
head=(head+1)%o;
point[head]=edge[i].v;
vis[edge[i].v]=true;
}
}
}
return dis[en];
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
MS(edge,0); MS(map1,-1); MS(point,0); MS(vis,0);
st=0x3f3f3f3f; en=0; itr=0;
FOR(i,1,n)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a-1,b,c);
if(st>a) st=a-1;
if(en<b+1) en=b;
}
FOR(i,st,en)
{
addedge(i,i+1,0);
addedge(i+1,i,-1);
}
ans=spfa(st,en);
printf("%d\n",ans);
}
return 0;
}
原文:http://www.cnblogs.com/cons/p/5239554.html