传送门
模拟赛的T3
没追求的我直接暴力BFS70分
很明显的需要记录状态
v
i
s
[
u
]
[
h
p
]
vis[u][hp]
vis[u][hp],表示是否出现过到点u,体力为hp这种情况
70分没毛病
比较秒的小优化思想是记录之前到过每个点的体力最大值,这样BFS时如果体力大于目标点之前最大体力才入队,vis数组就不用搞了
减少了好多冗余操作,这样一优化可以过90分
最后一个点需要2.25s,暂且当它过了吧
Code:
// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
struct Edge{
int to, next, len;
}edge[maxn << 1];
struct node{
int u, hp, tim;
};
int n, m, M, num, head[maxn], R[maxn], maxhp[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y, int z){ edge[++num] = (Edge){ y, head[x], z }; head[x] = num; }
int main(){
n = read(), m = read(), M = read();
for (int i = 1; i <= n; ++i) R[i] = read();
for (int i = 1; i <= m; ++i){
int x = read(), y = read(), z = read();
addedge(x, y, z); addedge(y, x, z);
}
maxhp[1] = M;
queue <node> q; q.push((node) {1, M, 0});
while (!q.empty()){
node tmp = q.front(); q.pop();
int u = tmp.u, hp = tmp.hp, tim = tmp.tim;
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to, Hp = hp - edge[i].len;
if (Hp <= 0) continue;
Hp = min(Hp + R[v], M);
if (Hp > maxhp[v]){
maxhp[v] = Hp; q.push((node) {v, Hp, tim + 1});
if (v == n){ printf("%d\n", tim + 1); return 0; }
}
}
}
puts("-1");
return 0;
}
下面是std算法

我不想写了,直接来std代码:
#include <cstdio>
#include <algorithm>
using namespace std;
int edge[500000],next[500000],dist[500000],first[200000];
int b[200000],d[200000],g[10000000],h[10000000],p[200000],r[200000];
int i,k,m,n,x,y,z,head,tail,sum_edge;
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (i=1;i<=n;i++)
scanf("%d",&r[i]);
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
sum_edge++,edge[sum_edge]=y,next[sum_edge]=first[x],dist[sum_edge]=z,first[x]=sum_edge;
sum_edge++,edge[sum_edge]=x,next[sum_edge]=first[y],dist[sum_edge]=z,first[y]=sum_edge;
}
d[1]=p[1]=k;
tail++,g[tail]=1,h[tail]=0;
for (head=1;head<=tail;head++)
{
if (g[head]==n)
{
printf("%d\n",h[head]);
return 0;
}
if (h[head]!=h[head-1])
for (i=head;i<=tail;i++)
d[g[i]]=p[g[i]],b[g[i]]=0;
for (i=first[g[head]];i!=0;i=next[i])
if ((d[g[head]]>dist[i]) && (min(d[g[head]]-dist[i]+r[edge[i]],k)>p[edge[i]]))
{
p[edge[i]]=min(d[g[head]]-dist[i]+r[edge[i]],k);
if (! b[edge[i]])
tail++,g[tail]=edge[i],h[tail]=h[head]+1,b[edge[i]]=1;
}
}
printf("-1\n");
return 0;
}
本文分享了模拟赛T3题目的解题思路,通过优化的BFS算法,记录到达各点的最大体力值,减少冗余操作,实现从70分提升至90分的解题策略。
175

被折叠的 条评论
为什么被折叠?



