首页 > 其他分享 >Full Tank 题解

Full Tank 题解

时间:2023-06-05 17:14:48浏览次数:50  
标签:Full Tank idx int 题解 vis cost now dis

Full Tank

题目大意

给定一张 \(n\) 个点,\(m\) 条边的连通无向图,在每个点有一个加油站,油价为该点的点权,每条边的油耗为该边的边权。现给出若干询问,问一辆油箱容量为 \(c\) 的车子是否能从 \(s\) 开到 \(e\),如果可以,求出最小所需的钱。

思路分析

看到这种有图有权求最小消耗的题,我们首先考虑最短路。

第一步,观察数据范围。

我们发现 \(c\) 较小,\(n\) 也不算大,这启示我们可以设计一个由剩余油量和点构成的二维状态,又因为存在多组询问,我们无法接受时间复杂度为 \(O(nmT)\) 的 SPFA,所以考虑用 Dijkstra。

第二步,考虑状态转移。

在跑正常的最短路时,对于每一个已经更新完毕的点,我们都借助它来更新其他点,但在这题中,我们设计了二维的状态,在每一个点都有两种操作:扣油去往其他的点或是原地不动花钱加油,我们需要同时考虑这两种操作。

具体的说,对于每一个二维的点 \((x,m)\)(\(x\) 表示当前位置,\(m\) 表示当前油量),我们可以用这个点更新点 \((x,m+1)(m+1\le c)\) 和所有的 \((y,m-w_{xy})(y\in \text{to}_x)\),更新方法类似于 Dijkstra。

然后就可以轻松写出代码了!

代码

#include <bits/stdc++.h>
using namespace std;
const int N=2010,M=20020,C=105;//点数,边数,最大油箱容量

int to[M],nxt[M],head[N],w[M],p[N];//图,边权,点权
int idx,n,m,c,s,e,in1,in2,in3,ans,Q;
int vis[N][C],dis[N][C];//二维的点,vis表示是否访问,dis是距离

struct node{int x,cost,you;}now;
bool operator < (node a,node b){return a.cost>b.cost;}//在优先队列中按所花的钱排序
priority_queue <node> q;

void add(int u,int v,int c){idx++;to[idx]=v;w[idx]=c;nxt[idx]=head[u];head[u]=idx;}

int bfs(int s){
    while(!q.empty()) q.pop();//一定要清空!!!
    memset(vis,0,sizeof vis);//初始化
    memset(dis,0x3f,sizeof dis);
    q.push(node{s,0,0});
    dis[s][0]=0;
    while(!q.empty()){
        now=q.top();q.pop();
        if(now.x==e) return now.cost;//到达终点
        if(vis[now.x][now.you]) continue;
        vis[now.x][now.you]=1;
        if(now.you<c) //如果当前油箱没有满
        if(dis[now.x][now.you+1]>now.cost+p[now.x]){
            dis[now.x][now.you+1]=now.cost+p[now.x];//更新状态
            q.push(node{now.x,now.cost+p[now.x],now.you+1});//加油,入队
        }
        for(int i=head[now.x];i;i=nxt[i]){
            if(now.you<w[i]) continue;//无法通过
            if(dis[to[i]][now.you-w[i]]>now.cost){//可以通过,更新状态
                dis[to[i]][now.you-w[i]]=now.cost;
                q.push(node{to[i],now.cost,now.you-w[i]});//扣油,入队
            }
        }
    }
    return -1;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&in1,&in2,&in3);
        in1++;in2++;//点从0到n-1,我们统一加1
        add(in1,in2,in3);add(in2,in1,in3);
    }
    scanf("%d",&Q);
    while(Q--){
        scanf("%d%d%d",&c,&s,&e);
        s++;e++;
        ans=bfs(s);
        if(ans==-1) puts("impossible");//无解
        else printf("%d\n",ans);
    }
    return 0;
}

标签:Full,Tank,idx,int,题解,vis,cost,now,dis
From: https://www.cnblogs.com/TKXZ133/p/17458276.html

相关文章

  • Visible Lattice Points 题解
    VisibleLatticePoints题目大意给定一个\(N×N×N\)的由若干点组成的立方体,点的坐标从\((0,0,0)\)到\((N,N,N)\),求从点\((0,0,0)\)处可以看见多少个点。思路分析我们将立方体上的点分成三类:在\(xy,yz,xz\)平面上的点。在\(x,y,z\)轴上的点。即不在平面,也不在......
  • Substring of Sorted String 题解
    SubstringofSortedString写篇题解纪念一下蒟蒻第一次赛时切出的F题。题目简述对一个字符串进行单点修改,区间判断操作。修改操作为将一个字符修改为另一个,判断操作为判断区间是否是整个字符串升序排序后的字串。思路分析蒟蒻第一眼线段树,但刚开始没仔细看题,以为是判断区......
  • DRTREE - Dynamically-Rooted Tree 题解
    DRTREE-Dynamically-RootedTree本题建议评蓝。思路:题目就是要对一颗不定根树求子树权值和。这题不带修,如果带修难度会增加一点,就跟遥远的国度差不多。首先分析一下在以不同根下子树的变化。当一颗树以1号节点为根时,比如说长这样:假设每个点的权值为1,那么这8个点......
  • 逛森林 题解
    P5344逛森林题目大意原题的题目大意已经很明确了要这个干嘛给定一些孤立点,将要进行两种操作:若两点之间不可以通过\(1\)类边连通,则在两点之间连双向\(1\)类边若\(u_1,v_1\)和\(u_2,v_2\)均可以通过\(1\)类边连通,则从\(u_1\tov_1\)的唯一路径上的所有点均向......
  • OTOCI 题解
    OTOCI题目大意给定\(n\)个带权的点,需要进行四种操作:查询两点连通性;加边;修改点权;查询两点路径的权值和。思路分析首先观察题目,我们会发现,在所有的操作结束后,所有的点构成一个森林,这是因为题目中的加边是建立在两点不连通的基础上的,所以不会形成任何的环,到最后自然形成了一个......
  • Sell Pigs 题解
    SellPigs双倍经验题目大意有\(n\)个顾客前来买猪,共有\(m\)个猪圈,每个顾客携带着某一些猪圈的钥匙,需要买一定数量的猪。在顾客买完后,我们可以将打开的猪圈中的猪随意移动,移动完毕后所有的猪圈将关闭,直到下一个顾客到来时才能打开其拥有钥匙对应的猪圈。求最多能卖出多少猪......
  • 旅游 题解
    旅游题目大意对一颗树进行两种操作:将一条从\(u\)到\(v\)的链上的点的权值增加\(x\);查询从\(u\)到\(v\)的链上最大的\(p_i-p_j(dis_{ui}<dis_{uj})\),其中\(p_i\)表示点\(i\)的权值,\(dis_{AB}\)表示点\(A,B\)间唯一路径上边的数量。思路分析先思考,如果没有\(d......
  • Interesting Array 题解
    InterestingArray题目大意构造一个序列\(a\),使其满足若干限制条件,每个限制条件是形如lrq的式子,其意义是:\(\&_{i=l}^ra_i=q\)。题意分析看上去是构造题,实际上是数据结构题。我们不妨先令初始时\(a\)为一个全\(0\)序列,再逐一看每个限制条件。为了满足某一个限制条件......
  • Sum of MSLCM 题解
    SumofMSLCM题目大意定义\(\text{MSLCM}(n)\)为所有满足该数集的\(\text{lcm}\)为\(n\)的数集中元素个数最多的数集的所有数字的和,现有多次询问,求\[\sum_{i=2}^n\text{MSLCM}(i)\]思路分析大水题。虽然看着这个东西很可怕,但仔细一想你就会发现,其实\(\text{MSLCM}(n)......
  • Java模拟表单提交编码不同导致乱码问题解决
    最近有个业务需要模拟表单提交到asp页面中,但是我的项目编码是UTF8,而asp页面是GB2312,中文字段提交后,到达数据库后是乱码.问题的解决在于模拟提交的时候指定编码:我用的HTTP框架是Unirest,代码如下:......