题目链接:http://poj.org/problem?id=3159
题意:n个点,m对A,B,C,表示B的值减A的值不超过C,求1和n的最大差值(后来我才知道这叫差分约束)。
分析:开始拿到这题有点懵比,没读懂,后来自己在草稿上画了画感觉就是求1点到n点的最短路。
如下图:
后来写了spfa+queue就交了上去T了一发,想了想,没招了,看了disscus发现说用堆栈可以,可是我不会呀!!!后来看了kuangbin的题解,才明白了这类题叫差分约束,也顺便学了一下写堆栈,还是很简单,也好理解的嘛。以下是kuangbin的分析:
/* /* 给n个人派糖果,给出m组数据,每组数据包含A,B,c 三个数, 意思是A的糖果数比B少的个数不多于c,即B的糖果数 - A的糖果数<= c 。 最后求n 比 1 最多多多少糖果。 【解题思路】 这是一题典型的差分约束题。不妨将糖果数当作距离,把相差的最大糖果数看成有向边AB的权值, 我们得到 dis[B]-dis[A]<=w(A,B)。看到这里,我们联想到求最短路时的松弛技术, 即if(dis[B]>dis[A]+w(A,B), dis[B]=dis[A]+w(A,B)。 即是满足题中的条件dis[B]-dis[A]<=w(A,B),由于要使dis[B] 最大, 所以这题可以转化为最短路来求。 这题如果用SPFA 算法的话,则需要注意不能用spfa+queue 来求,会TLE ,而是用 spfa + stackmy ugly code:
#include<cstdio>
#include<queue>
using namespace std;
const int INF=99999999,MAX_V=30000+5,MAX_E=150000+5;
struct edge{int v,w,next;}es[MAX_E];
bool visit[MAX_V];
int d[MAX_V],head[MAX_V];
int Q[MAX_V];
int V,E;
void spfa(){
for(int i=1;i<=V;++i)
visit[i]=false,d[i]=INF;
d[1]=0;visit[1]=true;
int top=0;
Q[top++]=1;visit[1]=true;//源点1入栈
while(top!=0){
int no=Q[--top];//出栈
visit[no]=false;
for(int i=head[no];i!=-1;i=es[i].next){
int to=es[i].v;
if(d[to]>es[i].w+d[no]){
d[to]=es[i].w+d[no];
if(!visit[to]){
visit[to]=true;
Q[top++]=to;
}
}
}
}
printf("%d\n",d[V]);
}
int main(void){
scanf("%d%d",&V,&E);
for(int i=1;i<=V;++i)
head[i]=-1;
for(int i=1;i<=E;++i){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
es[i].w=c;
es[i].v=b;
es[i].next=head[a];
head[a]=i;
}//加边。
spfa();
}
——— —— —— ——分界线
模拟栈:
int top=0;
Q[top++]=1//源点1入栈
while(top!=0)//栈不为空
int no =Q(--top);//出栈;