差分约束
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了差分约束相关的知识,希望对你有一定的参考价值。
刚学了差分约束系统。
差分约束就是给你一堆不等式,求一个满足条件的解。比如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; }
以上是关于差分约束的主要内容,如果未能解决你的问题,请参考以下文章