『算法-ACM竞赛-图论』差分约束-POJ3159Candies

『算法-ACM 竞赛-图论』差分约束-POJ3159Candies

图论–差分约束–POJ 3159 Candies

| Language:Default Candies Time Limit: 1500MS Memory Limit: 131072KTotal Submissions: 43021 Accepted: 12075 Description During the kindergarten days, flymouse was the monitor of his class. Occasionally the head-teacher brought the kids of flymouse’s class a large bag of candies and had flymouse distribute them. All the kids loved candies very much and often compared the numbers of candies they got with others. A kid A could had the idea that though it might be the case that another kid B was better than him in some aspect and therefore had a reason for deserving more candies than he did, he should never get a certain number of candies fewer than B did no matter how many candies he actually got, otherwise he would feel dissatisfied and go to the head-teacher to complain about flymouse’s biased distribution. snoopy shared class with flymouse at that time. flymouse always compared the number of his candies with that of snoopy’s. He wanted to make the difference between the numbers as large as possible while keeping every kid satisfied. Now he had just got another bag of candies from the head-teacher, what was the largest difference he could make out of it? Input The input contains a single test cases. The test cases starts with a line with two integers N and M not exceeding 30 000 and 150 000 respectively. N is the number of kids in the class and the kids were numbered 1 through N. snoopy and flymouse were always numbered 1 and N. Then follow M lines each holding three integers A, B and c in order, meaning that kid A believed that kid B should never get over c candies more than he did. Output Output one line with only the largest difference desired. The difference is guaranteed to be finite. Sample Input 2 2 1 2 5 2 1 4 Sample Output 5 Hint 32-bit signed integer type is capable of doing all arithmetic. Source POJ Monthly–2006.12.31, Sempr | Time Limit: 1500MS | | Memory Limit: 131072K | Total Submissions: 43021 | | Accepted: 12075 |
| Time Limit: 1500MS | | Memory Limit: 131072K |
| Total Submissions: 43021 | | Accepted: 12075 |

题意:幼儿园有 n 个小朋友分糖果,现在有 m 个如下形式的条件需要满足: a b c 表示 b 同学糖果数-a 同学糖果数<=c. 现在问你满足 m 个条件的情况下,要使得 n 号同学糖果数-1 号同学糖果数的差值最大为多少?

分析:

首先对于 m 个条件来说,如果 b-a<=c,那么从 a 到 b 有一条长 c 的边.现在我们要求的是 d[n]与 d[1]的差距最大,所以初始化应该令 d[1]=0,且 d[i]=INF( i>0). (根据百度百科对差分约束的介绍)

又由于该题中的 c 值都是正数,所以不会存在负权路或环.所以直接 Dijkstra 求 1 号点到其他所有点的最短距离即可得到解:d[n]-d[1].

根据算法导论的讲解,其实差分约束本来就是用最短路求解的.不过存在负权环的情况,所以用 BellmanFord 算法还可以判断出无解的情况.

AC 代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define INF 1e9
using namespace std;
const int maxn=30000+10;
const int maxm=150000+10;
struct Edge
{
    int from,to,dist;
    Edge(){}
    Edge(int f,int t,int d):from(f),to(t),dist(d){}
};
 
struct HeapNode
{
    int d,u;
    HeapNode(int d,int u):d(d),u(u){}
    bool operator<(const HeapNode &rhs)const
    {
        return d>rhs.d;
    }
};
 
struct Dijkstra
{
    int n,m;
    int head[maxn],next[maxm];
    Edge edges[maxm];
    int d[maxn];
    bool done[maxn];
 
    void init(int n)
    {
        this->n=n;
        m=0;
        memset(head,-1,sizeof(head));
    }
 
    void AddEdge(int from,int to,int dist)
    {
        edges[m]=Edge(from,to,dist);
        next[m]=head[from];
        head[from]=m++;
    }
 
    int dijkstra()
    {
        priority_queue<HeapNode> Q;
        for(int i=0;i<n;i++) d[i]= i==0?0:INF;
        memset(done,0,sizeof(done));
        Q.push(HeapNode(d[0],0));
 
        while(!Q.empty())
        {
            HeapNode x=Q.top(); Q.pop();
            int u=x.u;
            if(done[u]) continue;
            done[u]=true;
            for(int i=head[u];i!=-1;i=next[i])
            {
                Edge &e=edges[i];
                if(d[e.to]>d[u]+e.dist)
                {
                    d[e.to]= d[u]+e.dist;
                    Q.push(HeapNode(d[e.to],e.to));
                }
            }
        }
        return d[n-1];
    }
 
}DJ;
 
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    DJ.init(n);
    while(m--)
    {
        int u,v,d;
        scanf("%d%d%d",&u,&v,&d);
        u--,v--;
        DJ.AddEdge(u,v,d);
    }
    printf("%d\n",DJ.dijkstra());
    return 0;
}

『算法-ACM竞赛-图论』差分约束-POJ3159Candies
https://chiamzhang.github.io/2024/06/29/『算法-ACM竞赛-图论』差分约束-POJ3159Candies/
Author
Chiam
Posted on
June 29, 2024
Licensed under