天天看点

POJ 3159 Candies(Dijkstra算法+优先队列+堆)

Candies

Time Limit: 1500MS Memory Limit: 131072K
Total Submissions: 37796 Accepted: 10637

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

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
struct CNode{
    int k,w;
    bool operator<(const CNode &d1)const{
    return w>d1.w;
    }
};
priority_queue<CNode> pq;
bool bUsed[30010]={0};

vector<vector<CNode> > v;//v是整个图的邻接表
const int INFINITE=100000000;
int main(){
    int N,M;
    int a,b,c;
    scanf("%d%d",&N,&M);
    CNode p;
    v.clear();//邻接表清空
    v.resize(N+1);//邻接表扩容
    memset(bUsed,0,sizeof(bUsed));//访问数组标记
    for(int i=1;i<=M;i++){
        scanf("%d %d %d",&a,&b,&c);
        p.k=b;
        p.w=c;
        v[a].push_back(p);//将p放入邻接表
    }
    //针对访问自己的情况
    p.k=1;
    p.w=0;
    pq.push(p);//将p按照优先队列的规则加入pq
    while(!pq.empty()){
        p=pq.top();
        pq.pop();
        if(bUsed[p.k])//求出了最短路
            continue;
        bUsed[p.k]=true;//标记为已访问
        if(p.k==N)//保证不形成回路
            break;
        for(int i=0,j=v[p.k].size();i<j;i++){
            CNode q;q.k=v[p.k][i].k;
            if(bUsed[q.k]) continue;
            q.w=p.w+v[p.k][i].w;
            pq.push(q);
        }
    }
    printf("%d\n",p.w);
    return 0;
}
           

思路:主要是用vector容器构造一个邻接表,用来存储每一行的信息。那么怎么把优先队列和邻接表联系起来呢?

           优先队列的主要操作:

           常用的操作如下:

           empty()  如果优先队列为空,则返回真 

           pop()  删除第一个元素 

           push()  加入一个元素 

           size()  返回优先队列中拥有的元素的个数 

           top()  返回优先队列中有最高优先级的元素 

          push_back函数,在vector类中作用为在vector尾部加入一个数据。

         我们把每一行的三个数据a,b,c输入进去,b和c分别定义为p.k和p.w,然后从尾部依次加入邻接表p

        然后我们把p中的元素依次加入优先队列pq,按照优先队列规定的规则进行排序,执行top和pop操作。

        因为STL优先队列存在局限性,那就是只提供入队、出队、取得队首元素的值的功能,而dijkstra算法的堆优化需要能够随机访问队列中某个节点(来更新源点节点的最短距离)。所以我们需要进行遍历,对权值进行更新操作。在权值更新完成之后,输出找出的最小权值,结束程序。