POJ-3159 Candies 最短路应用(差分约束)

题目链接:https://cn.vjudge.net/problem/POJ-3159

题意

给出一组不等式
求第一个变量和最后一个变量可能的最大差值
数据保证有解

思路

一个不等式a-b<=c,通过移项,实际上就是满足了a<=b+c
发现在整个约束系统中,a在下满足不等式的情况下求最大值,就是在求最短路

然而如果直接用BellmanFord(spfa)的话,还是会超时
这时得对Bellman做第二次优化,用stack代替queue
但是对于更多的图中,Dijsktra依然更优,所以没有必要太过考虑这个问题?

代码

Dijkstra

#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=3e4+20, maxm=15e4+20, INF=0x3f3f3f3f;
typedef pair<int, int> Node;
struct Cmp{
    bool operator () (const Node &a, const Node &b){
        return a.first>b.first;
    }
};
struct Edge{
    int to, dis, next;
}edges[maxm+5];
int head[maxn+5], size=0;

void addEdge(int from, int to, int dis){
    edges[size]=Edge{to, dis, head[from]};
    head[from]=size++;
}

void init(void){
    memset(head, -1, sizeof(head));
    size=0;
}

int Bellman(int n){
    int dist[maxn+5], sta[maxn+5], top=0;//cnt[maxn+5];
    bool inq[maxn+5]={false};
    // queue<int> que;

    memset(dist, INF, sizeof(dist)); dist[1]=0;
    sta[top++]=1;
    while (top!=0){
        int from=sta[--top];
        inq[from]=false;

        for (int i=head[from]; i!=-1; i=edges[i].next){
            Edge &e=edges[i];
            int &to=e.to, &dis=e.dis;

            if (dist[to]<=dist[from]+dis) continue;
            dist[to]=dist[from]+dis;

            if (inq[to]) continue;
            sta[top++]=to; inq[to]=true;
        }
    }return dist[n];
}

int Dij(int n){
    int dist[maxn+5];
    priority_queue<Node, vector<Node>, Cmp> que;

    memset(dist, INF, sizeof(dist)); dist[1]=0;
    que.push(Node(dist[1], 1));
    while (que.size()){
        Node x=que.top(); que.pop();
        if (x.first!=dist[x.second]) continue;

        int &from=x.second;
        for (int i=head[from]; i!=-1; i=edges[i].next){
            Edge &e=edges[i];
            int &to=e.to, &dis=e.dis;

            if (dist[to]<=dist[from]+dis) continue;
            dist[to]=dist[from]+dis;
            que.push(Node(dist[to], to));
        }
    }return dist[n];
}

int main(void){
    int n, m, from, to, dis;

    init();
    scanf("%d%d", &n, &m);
    for (int i=0; i<m; i++){
        scanf("%d%d%d", &from, &to, &dis);
        addEdge(from, to, dis);
    }printf("%d\n", Dij(n));//Bellman(n));

    return 0;
}
Time Memory Length Lang Submitted
532ms 2568kB 1960 G++ 2018-05-27 00:47:58

BellmanFord

#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=3e4+20, maxm=15e4+20, INF=0x3f3f3f3f;
struct Edge{
    int to, dis, next;
}edges[maxm+5];
int head[maxn+5], size=0;

void addEdge(int from, int to, int dis){
    edges[size]=Edge{to, dis, head[from]};
    head[from]=size++;
}

void init(void){
    memset(head, -1, sizeof(head));
    size=0;
}

int Bellman(int n){
    int dist[maxn+5], sta[maxn+5], top=0;//cnt[maxn+5];
    bool inq[maxn+5]={false};
    // queue<int> que;

    memset(dist, INF, sizeof(dist)); dist[1]=0;
    sta[top++]=1;
    while (top!=0){
        int from=sta[--top];
        inq[from]=false;

        for (int i=head[from]; i!=-1; i=edges[i].next){
            Edge &e=edges[i];
            int &to=e.to, &dis=e.dis;

            if (dist[to]<=dist[from]+dis) continue;
            dist[to]=dist[from]+dis;

            if (inq[to]) continue;
            sta[top++]=to; inq[to]=true;
        }
    }return dist[n];
}

int main(void){
    int n, m, from, to, dis;

    init();
    scanf("%d%d", &n, &m);
    for (int i=0; i<m; i++){
        scanf("%d%d%d", &from, &to, &dis);
        addEdge(from, to, dis);
    }printf("%d\n", Bellman(n));

    return 0;
}
Time Memory Length Lang Submitted
485ms 2108kB 1220 G++ 2018-05-27 00:39:53

posted on 2018-06-01 23:40  糖栗子  阅读(148)  评论(0编辑  收藏  举报

导航