http://poj.org/problem?id=3159
题意:幼儿园有
n
n
个小朋友,设第个小朋友得到的糖果数为
v[i]
v
[
i
]
,有
m
m
个约束条件,表示得到的糖果数不能多于
A
A
得到的糖果数个,即
v[B]−v[A]<=C
v
[
B
]
−
v
[
A
]
<=
C
,求第
1
1
个小朋友与第个小朋友糖果数差值的最大值,即求在满足这
m
m
个条件的情况下,的最大值。
标准的差分约束题,A向B连一条长为C的边,跑最短路得到的就是答案。具体差分约束的讲解参考博客https://blog.csdn.net/consciousman/article/details/53812818
这里要注意的就是,最短路可以用Dijkstra+Heap求,也可以用SPFA,但是这道题卡队列的SPFA,要用栈跑,用队列会超时。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<cstring>
#define INF 0x3f3f3f
using namespace std;
const int maxn=30010,maxm=150010;
int head[maxn],k=1,n,m,x,y,a,b,dis[maxn],sum[maxn];
bool vis[maxn];
struct edge{
int w,v,next;
}e[maxm];
void addedge(int u,int v,int w){e[k].v=v;e[k].w=w;e[k].next=head[u];head[u]=k++;}
void spfa(int s)
{
long long res=0;
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
stack<int> q;
dis[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
int t=q.top();
vis[t]=0;
q.pop();
for(int i=head[t];i;i=e[i].next)
{
int v=e[i].v;
if(dis[v]>dis[t]+e[i].w)
{
dis[v]=dis[t]+e[i].w;
if(!vis[v])
{
vis[v]=1;
q.push(v);
sum[v]++;
if(sum[v]>n)
return ;
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&x);
addedge(a,b,x);
}
long long ans=0;
spfa(1);
printf("%d\n",dis[n]);
return 0;
}