poj 3159 Candies(差分约束系统)

题目链接: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;
}


你可能感兴趣的:(poj 3159 Candies(差分约束系统))