POJ 3159 Candies(差分约束+spfa+链式前向星)
题目链接:http://poj.org/problem?id=3159
题目大意:给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)因为要使A,B间满足dis[B]-dis[A]<=w(A,B)右要使差值最大,所以dis[B]=dis[A]+w(A,B)。
所以这题可以转化为最短路来求。注意:很坑,这题的spfa被卡了,要用栈才不会超时。
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<queue> 6 #include<stack> 7 using namespace std; 8 const int N=2e5+5; 9 10 struct node{ 11 int to,next,w; 12 }edge[N]; 13 14 int n,m; 15 int idx,head[N]; 16 //初始化 17 void init(){ 18 idx=1; 19 memset(head,-1,sizeof(head)); 20 } 21 //添加边 22 void addEdge(int u,int v,int w){ 23 edge[idx].to=v; 24 edge[idx].w=w; 25 edge[idx].next=head[u]; 26 head[u]=idx; 27 idx++; 28 } 29 30 int dis[N]; 31 bool vis[N]; 32 void spfa(int s){ 33 memset(dis,0x3f,sizeof(dis)); 34 dis[s]=0; 35 stack<int>sk; 36 sk.push(s); 37 while(!sk.empty()){ 38 int k=sk.top(); 39 sk.pop(); 40 vis[k]=false; 41 for(int i=head[k];i!=-1;i=edge[i].next){ 42 node t=edge[i]; 43 //改变了松弛条件 44 if(dis[t.to]>dis[k]+t.w){ 45 dis[t.to]=dis[k]+t.w; 46 if(!vis[t.to]){ 47 sk.push(t.to); 48 vis[t.to]=true; 49 } 50 } 51 } 52 } 53 } 54 55 int main(){ 56 init(); 57 scanf("%d%d",&n,&m); 58 for(int i=1;i<=m;i++){ 59 int a,b,w; 60 scanf("%d%d%d",&a,&b,&w); 61 addEdge(a,b,w); 62 } 63 spfa(1); 64 printf("%d\n",dis[n]-dis[1]); 65 return 0; 66 }