poj 3159 Candies 差分约束

poj 3159 Candies 差分约束
//poj 3159 Candies

//差分约束
//不了解差分约束的可以看看这个
//http://hi.baidu.com/qinning199/item/65d270215bb365182a0f1c07
//这题是我的第一题差分约束

//题意:
//有n个孩子分糖果,m个孩子的要求,没个要求都有三个数A,B,c
//表示A孩子要求B孩子拿到的糖果不能超过自己 c个

//思路:
//其实主要就是找出类似最短路中的三角不等式d[v]<=d[u]+w[u,v]
//找到这关系后,就可以根据最短路来求解了,求出来的dis数组就是满足每
//个孩子要求的前提下,分配给每个孩子的糖果数
//这题边太多 卡用队列的spfa,用优先队列优化的dijsktra就可以500多ms  ac

#define comein freopen("in.txt", "r", stdin);
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;

#define INF 1<<30
#define N 30005

struct EDGE
{
    int to, dis, next;
}edge[150005];

struct S
{
    int pos, dis;
    S(int pos, int d)
    {
        this->pos = pos;
        this->dis = d;
    }
    S(){}
    bool operator < (const S &other)const
    {
        return this->dis > other.dis;
    }
};

int tot;
int head[N], dis[N];
bool vis[N];

void add_edge(int from, int to, int d)
{
    edge[++tot].to = to;
    edge[tot].dis = d;
    edge[tot].next = head[from];
    head[from] = tot;
}

void dijsktra(int n_kid)
{
    priority_queue<S> que;
    dis[1] = 0;
    int now = 1;
    while(1)
    {
        vis[now] = true;
        for(int i = head[now]; i != -1; i = edge[i].next)
        {
            int to = edge[i].to;
            if(vis[to] == false && (dis[to] == -1 ||dis[to] - dis[now] > edge[i].dis))
            {
                dis[to] = dis[now] + edge[i].dis;
                que.push(S(to, dis[to]));
            }
        }
        int tmp = now;
        while(!que.empty())
        {
            S ttt = que.top();
            que.pop();
            if(vis[ttt.pos] == false)
            {
                now = ttt.pos;
                break;
            }
        }
        if(tmp == now)
            break;
    }
}

//void spfa(int n_kid)    //TLE
//{
//    queue<int>que;
//    dis[1] = 0;
//    que.push(1);
//    vis[1] = true;
//    while(!que.empty())
//    {
//        int now = que.front();
//        que.pop();
//        for(int i = head[now]; i != -1; i = edge[i].next)
//        {
//            int to = edge[i].to;
//            if(dis[to] == -1 || dis[to] - dis[now] >= edge[i].dis)
//            {
//                dis[to] = dis[now] + edge[i].dis;
//                if(vis[to] == false)
//                {
//                    que.push(to);
//                    vis[to] = true;
//                }
//            }
//        }
//        vis[now] = false;
//    }
//}

int main()
{
    comein
    int n_kid, m;
    while(scanf("%d%d", &n_kid, &m) != EOF)
    {
        tot = 0;
        for(int i = 1; i <= n_kid; ++i)
        {
            head[i] = -1;
            vis[i] = false;
            dis[i] = -1;
        }
        for(int i = 0; i < m; ++i)
        {
            int from, to, d;
            //x1孩子 认为 x2 孩子的糖果不能超过自己c个
            //x1 - x2 <= c ->  dis[to] - dis[from] <= d
            //那如果 dis[to] - dis[from] >= d的话我们就要维护
            //让他保持dis[to] - dis[from] <= d 得到的就是正确的解
            scanf("%d%d%d", &from, &to, &d);
            add_edge(from, to, d);
        }
//        spfa(n_kid);    //TLE
        dijsktra(n_kid);
        printf("%d\n", dis[n_kid]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/gabo/p/2617630.html