Full Tank? UVA - 11367

本文介绍了解决 UVA-11367 题目的方法,该题涉及图论中的最短路径问题。具体地,针对带有燃料限制的路径寻找最小花费,使用 SPFA 算法进行求解。

Full Tank? UVA - 11367

图论·最短路

题目大意:

n个点m条无向边的图,每个单位的汽油能走1单位距离,每个城市的油价p[i],油箱有上限c, 对于每个询问,求s到t的最小花费。

题解:

d[u][oilu]在d这个点剩余油量为oilu的最小花费。
只要油还够,就可以向与它相连的v转移,d[v][oilu-w(u,v)]
注意如果直接枚举加多少油会T。
因此每次只加一格油,也就是只+p[u]转移到d[u][oilu+1].

感觉一直在刷水题。。。

Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define MP make_pair
using namespace std;
typedef pair<int,int> pii;
const int N = 2005;
const int M = 50005;
const int INF = 0x3f3f3f3f;

int n,m,p[N],q;

struct Edge{
    int to,next,w;
}e[M];
int head[N],ec;
void clear(){ memset(head,0,sizeof(head)); ec=0; }
void add(int a,int b,int w){
    ec++; e[ec].to=b; e[ec].w=w;
    e[ec].next=head[a]; head[a]=ec;
}

bool vis[N][105]; int d[N][105];
void spfa(int s,int t,int c){
    memset(vis,false,sizeof(vis));
    memset(d,0x3f,sizeof(d));
    queue<pii> q; q.push(MP(s,0)); vis[s][0]=true; d[s][0]=0;
    while(!q.empty()){
        int u=q.front().first; int oilu=q.front().second; q.pop(); vis[u][oilu]=false;
        if(oilu+1<=c && d[u][oilu+1]>d[u][oilu]+p[u]){
            d[u][oilu+1]=d[u][oilu]+p[u];
            if(!vis[u][oilu+1]){
                vis[u][oilu+1]=true; q.push(MP(u,oilu+1));
            }
        }
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to; int cost=e[i].w;
            if(oilu<cost) continue;
            if(d[v][oilu-cost]>d[u][oilu]){
                d[v][oilu-cost]=d[u][oilu];
                if(!vis[v][oilu-cost]){
                    vis[v][oilu-cost]=true; q.push(MP(v,oilu-cost));
                }
            }
        }
    }
}

int main(){
    freopen("a.in","r",stdin);
    while(~scanf("%d%d",&n,&m)){
        clear();
        for(int i=1;i<=n;i++) scanf("%d",&p[i]);
        int a,b,w;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&w);
            a++; b++;
            add(a,b,w); add(b,a,w);
        }
        scanf("%d",&q);
        int s,t,c;
        while(q--){
            scanf("%d%d%d",&c,&s,&t);
            s++; t++;
            spfa(s,t,c);
            if(d[t][0]==INF) puts("impossible");
            else printf("%d\n",d[t][0]);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值