题目链接:http://poj.org/problem?id=3159
以下定义摘自百度百科:
如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如xj-xi<=bk(i,j∈[1,n],k∈[1,m]),则称其为差分约束系统(system of difference constraints)。亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。
如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如xj-xi<=bk(i,j∈[1,n],k∈[1,m]),则称其为差分约束系统(system of difference constraints)。亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。
求解差分约束系统,可以转化成图论的单源最短路径(或最长路径)问题。
观察xj-xi<=bk,会发现它类似最短路中的三角不等式d[v]<=d[u]+w[u,v],即d[v]-d[u]<=w[u,v]。因此,以每个变量xi为结点,对于约束条件xj-xi<=bk,连接一条边(i,j),边权为bk。我们再增加一个源点s,s与所有定点相连,边权均为0。对这个图,以s为源点运行Bellman-ford算法(或SPFA算法),最终{d[ i]}即为一组可行解。
这道题是一个模版题,注意不能用spfa+队列,会被卡时。
#include<iostream> #include<cstdio> using namespace std; const int INF=0x3f3f3f3f; const int maxn=30010; int n,m; int e,head[maxn],dis[maxn],inQueue[maxn],stack[maxn]; bool vis[maxn]; struct node{ int to; int w; int next; }edge[150010]; void init(){ e=0; memset(dis,INF,sizeof(dis)); memset(head,-1,sizeof(head)); memset(inQueue,0,sizeof(inQueue)); } void addEdge(int u,int v,int w){ edge[e].to=v,edge[e].w=w,edge[e].next=head[u]; head[u]=e++; } int spfa(){ int top=0; stack[top++]=1; vis[1]=1,inQueue[1]=1,dis[1]=0; while(top){ int u=stack[--top]; vis[u]=0; if(inQueue[u]>n) return -1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(dis[v]>dis[u]+edge[i].w){ dis[v]=dis[u]+edge[i].w; if(!vis[v]){ inQueue[v]++; vis[v]=1; stack[top++]=v; } } } } return dis[n]; } int main(){ while(~scanf("%d%d",&n,&m)){ init(); int a,b,c; while(m--){ scanf("%d%d%d",&a,&b,&c); addEdge(a,b,c); } int ans=spfa(); printf("%d\n",ans); } return 0; }