poj 3159 Candies

这题目做的一个纠结啊。

N个人份糖果,其中含有约束条件,即对于a,b,c有 b-a<=c,看到这个不等式马上感觉到要用最短路解决了,问Sn-S1的最大值是多少,我们令S1=0即求Sn的最大值,查分约束题目,
求最短路,初始原点1到2,3,..,n的距离为INF,每次松弛找到第一组满足约束条件的解,这个解就是最大值,但是这个题目有问题啊,用最常用的bellman_ford无法通过啊,n,m值太大了,只能用spfa或者其他的优化方法,这个题用spfa+stack,用queue也会超时的,我猜想可能stack的访问效率较后者快吧,我最开始用的dijkstra+优先队列,不是超时就是WA,WA的时候我真搞不明白为什么,感觉很简单的题目怎么回WA呢,郁闷死了。。下面附上spfa+stack的代码吧。刚明白为什么我刚才用di。。为何错误了,由于一个节点可以多次如队列,这样由于入队列的仅仅是一个简单的int,无法区分,我们只需定义一个结构体包含节点号及当前len即可,两种方法都a了,。。

#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
using namespace std;
const int N=150002;
const int INF=10000000;
struct node{
    int to,next,weight;
};
node edge[N];
int num,n,m,dist[30002],adj[30002];
struct cmp
{
    bool operator() (const int &a, const int &b)
    {
        return dist[a] > dist[b];
    }
};
void dijkstra(int s)
{
    int u,i,v,w;
    bool visit[30002];
    for(i=0;i<=n;i++)
    {
        dist[i]=INF;
        visit[i]=false;
    }
    dist[s]=0;
    int Stack[30002],top=0;
    Stack[top++]=s;
    visit[s]=true;
    while(top)
    {
        u=Stack[--top];
        visit[u]=false;
        for(i=adj[u];i!=-1;i=edge[i].next)
        {
        //    cout<<dist[u]<<" "<<edge[i].weight<<" "<<dist[edge[i].to]<<endl;
            v=edge[i].to;
            w=edge[i].weight;
            if(dist[v]>dist[u]+w)
            {
                dist[v]=dist[u]+w;
                if(!visit[v])
                {
                    Stack[top++]=v;
                    visit[v]=true;
                }
            }
        }
    }
    printf("%d\n",dist[n]);
}
int main()
{
    scanf("%d%d",&n,&m);
    int i,a,b,w;
    num=0;
    for(i=0;i<=n;i++)
        adj[i]=-1;
    for(i=0;i<m;i++)
    {
        scanf("%d%d%d",&a,&b,&w);
        edge[num].to=b;
        edge[num].weight=w;
        edge[num].next=adj[a];
        adj[a]=num++;
    }
    dijkstra(1);
    return 0;
}

下面的是dijkstra+优先队列,只贴核心:

    priority_queue<qNode> q;
    qNode tmp,newNode;
    tmp.x=s;
    tmp.d=0;
    q.push(tmp);
    while(!q.empty())
    {
        tmp=q.top();q.pop();
        u=tmp.x;
        if(visit[u])
            continue;
        visit[u]=true;
        if(u == n)
            break;
        for(i=adj[u];i!=-1;i=edge[i].next)
        {
        //    cout<<dist[u]<<" "<<edge[i].weight<<" "<<dist[edge[i].to]<<endl;
            v=edge[i].to;
            w=edge[i].weight;
            if(!visit[v] && dist[v]>dist[u]+w)
            {
                dist[v]=dist[u]+w;
                newNode.x=v;
                newNode.d=dist[v];
                q.push(newNode);
            }
        }
    }

原文地址:https://www.cnblogs.com/buptLizer/p/2173407.html