light oj 1254

题目大意:n个点m条边的有向图,q次询问c,s,t,表示汽车邮箱容量为c,求从起点s到终点t的最小费用。汽车在每个点可以加任意的油,每个点的单位油价为a[i]。

题目思路:利用最小费优先队列优化最短路,dist[u][use]代表到达u节点,剩余use单位汽油的花费值。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define MAXSIZE 1015
#define INF 0x3f3f3f3f
#define LL long long

using namespace std;

typedef pair<int,int>p;
typedef pair<p,int>pp;

int dist[MAXSIZE][105],val[105],a[2*MAXSIZE],k;

struct node
{
    int u;
    int v;
    int w;
    int next;
} G[2*MAXSIZE];

void Add(int u,int v,int w)
{
    G[k].u=u;
    G[k].v=v;
    G[k].w=w;
    G[k].next=a[u];
    a[u]=k++;
}

int spfa(int s,int t,int c)
{
    memset(dist,INF,sizeof(dist));
    priority_queue<pp,vector<pp>,greater<pp> >Q;
    dist[s][0]=0;
    Q.push(pp(p(dist[s][0],0),s)); // 按优先级顺序入队
    while(!Q.empty())
    {
        pp k=Q.top();
        Q.pop();
        int w=k.first.first; //已花费的钱
        int use=k.first.second; //剩余油量
        int u=k.second; //当前节点
        if(w > dist[u][use])
            continue;
        if(u==t) //最小费优先
            return dist[u][use];
        for(int i=a[u]; i!=-1; i=G[i].next)
        {
            int v=G[i].v;
            if(G[i].w > c)
                continue;
            if(use >= G[i].w && dist[v][use - G[i].w] > dist[u][use]) //当前剩余油量足够到达v
            {
                dist[v][use - G[i].w] = dist[u][use];
                Q.push(pp(p(dist[v][use - G[i].w],use - G[i].w),v));
            }

        }
        if(use < c)//当前油量不足以到达下一个点,就向邮箱里加1个单位的汽油
        {
            dist[u][use+1] = dist[u][use] + val[u];
            Q.push(pp(p(dist[u][use+1],use+1),u));
        }
    }
    return INF;
}

void Init()
{
    memset(a,-1,sizeof(a));
    k=1;
}

int main()
{
    int T,n,m,c,s,t,u,v,w,cns=1;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
            scanf("%d",&val[i]);
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            Add(u,v,w);
            Add(v,u,w);
        }
        scanf("%d",&m);
        printf("Case %d:
",cns++);
        while(m--)
        {
            memset(dist,INF,sizeof(dist));
            scanf("%d%d%d",&c,&s,&t);
            int ans=spfa(s,t,c);
            if(ans != INF)
                printf("%d
",ans);
            else
                printf("impossible
");
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/alan-W/p/6767349.html