POJ 3159 Candies(dijkstra+heap&spfa+stack)

题目链接: kuangbin带你飞 专题四 最短路练习 K - Candies

题意

给n个人分糖果,m组数据a,b,c;意思是a比b少的糖果个数绝对不超过c个,也就是d(b)-d(a) < c,求1比n少的糖果数的最大值。

思路

也是通过这个题第一次接触到差分约束这个东西,学习了下,很奇妙。
令x-y<=z表示x最大比y大z。
若b-a<=k1, c-b<=k2, c-a<=k3,那么c-a最大为多少呢?显然应该等于min(k1+k2, k3)。可以用下图来表示示(不擅图丑勿怪)

这样的情况跟图论里的最短路极其相似,故此我们可以将其转换为对1到n的最短路求解的问题。
最短路,dijkstra,spfa都可
本人一开始用spfa+queue,直接超时,看别人题解都说是
spfa用队列维护数据会超时,用栈可以通过,果然,直接ac(这点我相当奇怪,关于栈与队列在实现spfa上的效率一直没有什么定论。为何在本体上相差这么多(一个
500ms,一个1500ms还不够)。好多人说是测试数据的问题)
总之虽然用spfa+stack过了,但不知缘由的ac令人相当不舒服,所以又用dijkstra写了一遍(需要heap优化,否则也会超时)

代码

dijkstra+heap

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;

const int N = 150009;
const int MAX = 0x3f3f3f3f;

bool vis[N];
int d[N];
int ans[N] = {};
int head[N];
struct Edge
{
    int u, v, w, next;
}e[N];

struct Node
{
    int x, v;
    Node(int a, int b): x(a), v(b) {}
    bool operator < (const Node &t) const
    {
        return this->v > t.v;
    }
};

int dijkstra(int n)
{
    memset(vis, 0, sizeof(vis));
    memset(d, 0x3f3f3f3f, sizeof(d));
    priority_queue<Node, vector<Node> > q;
    for(int i=head[1]; i!=-1; i=e[i].next)
        d[e[i].v] = e[i].w;
    for(int i=2; i<=n; i++)
        q.push(Node(i,d[i]));
    d[1] = 0;

    vis[1] = 1;

    for(int k=1; k<n && !q.empty(); k++)
    {
        Node t = Node(0, 0);
        do{
            t = q.top();q.pop();
        }while(vis[t.x] && !q.empty());
        int x = t.x;
        if(x == -1)
            break;
        vis[x] = 1;
        for(int i=head[x]; i!=-1; i=e[i].next)
        {
            if(!vis[e[i].v] && d[e[i].v] > d[x] + e[i].w)
            {
                d[e[i].v] = d[x] + e[i].w;
                q.push(Node(e[i].v, d[e[i].v]));
            }
        }
    }
    return d[n];
}

int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        memset(ans, 0, sizeof(ans));
        memset(head, -1, sizeof(head));
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
            e[i].next = head[e[i].u];
            head[e[i].u] = i;
        }
        printf("%d\n", dijkstra(n));
    }
    return 0;
}

spfa+stack

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<stack>

using namespace std;

const int N = 150009;
const int MAX = 0x3f3f3f3f;

bool vis[N];
int d[N];
int ans[N] = {};
int head[N];
struct Edge
{
    int u, v, w, next;
}e[N];

int spfa(int n)
{
    memset(vis, 0, sizeof(vis));
    for(int i=1; i<=n; i++)
        d[i] = MAX;
    d[1] = 0;
    vis[1] = 1;
    stack<int> s;
    s.push(1);
    while(!s.empty())
    {
        int x = s.top();
        s.pop();
        vis[x] = 0;
        for(int i=head[x]; i!=-1; i=e[i].next)
        {
            if(d[e[i].v] > d[x] + e[i].w)
            {
                d[e[i].v] = d[x] + e[i].w;
                if(!vis[e[i].v])
                {
                    s.push(e[i].v);
                    vis[e[i].v] = 1;
                }
            }
        }
    }
    return d[n];
}

int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        memset(ans, 0, sizeof(ans));
        memset(head, -1, sizeof(head));
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
            e[i].next = head[e[i].u];
            head[e[i].u] = i;
        }
        printf("%d\n", spfa(n));
    }
    return 0;
}