POJ - 3159 Candies

/*
POJ 3159
差分約束+SPFA

給n個人派糖果,給出m組數據,每組數據包含A,B,c  三個數,
意思是A的糖果數比B少的個數不多於c,即B的糖果數 - A的糖果數<= c 。
最後求n 比 1 最多多多少糖果。
【解題思路】
這是一題典型的差分約束題。不妨將糖果數當作距離,把相差的最大糖果數看成有向邊AB的權值,
我們得到 dis[B]-dis[A]<=w(A,B)。看到這裏,我們聯想到求最短路時的鬆弛技術,
即if(dis[B]>dis[A]+w(A,B), dis[B]=dis[A]+w(A,B)。
即是滿足題中的條件dis[B]-dis[A]<=w(A,B),由於要使dis[B] 最大,
所以這題可以轉化爲最短路來求。
這題如果用SPFA 算法的話,則需要注意不能用spfa+queue 來求,會TLE ,而是用 spfa + stack


2012-8-17

//SPFA的隊列實現會超時,堆棧實現可以。
//沒有負環迴路判斷,堆棧實現SPFA(有時候堆棧確實比較快)

//G++ 516ms

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;


const int MAXN=30010;
const int MAXE=150010;
const int INF=0x3f3f3f3f;
int head[MAXN];//每個結點的頭指針
int vis[MAXN];//在隊列標誌


int Q[MAXN];//堆棧
int dist[MAXN];


struct Edge
{
    int to;
    int v;
    int next;
}edge[MAXE];
int tol;
void add(int a,int b,int v)//加邊
{
    edge[tol].to=b;
    edge[tol].v=v;
    edge[tol].next=head[a];
    head[a]=tol++;
}
void SPFA(int start,int n)
{
    int top=0;
    for(int v=1;v<=n;v++)//初始化
    {
        if(v==start)
        {
            Q[top++]=v;
            vis[v]=true;
            dist[v]=0;
        }
        else
        {
            vis[v]=false;
            dist[v]=INF;
        }
    }
    while(top!=0)
    {
        int u=Q[--top];
        vis[u]=false;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dist[v]>dist[u]+edge[i].v)
            {
                dist[v]=dist[u]+edge[i].v;
                if(!vis[v])
                {
                    vis[v]=true;
                    Q[top++]=v;
                }
            }
        }
    }
}
int main()
{
   // freopen("in.txt","r",stdin);
  //  freopen("out.txt","w",stdout);
    int n;
    int M;
    int a,b,c;
    while(scanf("%d%d",&n,&M)!=EOF)
    {
        tol=0;//加邊計數,這個不要忘
        memset(head,-1,sizeof(head));
        while(M--)
        {
            scanf("%d%d%d",&a,&b,&c);
            //b-a<=c
            add(a,b,c);
            //大-小<=c ,有向邊(小,大):c
        }
        SPFA(1,n);
        printf("%d\n",dist[n]);
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章