2110D Div. 2 Round 1026
题意
给定一个\(n\)点\(m\)边的图 , 每个点上有一个数字\(b_i\)表示第\(i\)个检查点的电池数量 , \(m\)条边 , 边权为通过该边需要的电池数
每当到达一个点时 , 电池数加上该点的电池数 , 并且所有电池都充满电
思路
有点像小明妈妈找小明的题 , 我也是这么写的
二分 + dfs , 但是31的时候tle了
考虑优化 , 从出发点开始 , 更新所有能经过的点 , 在更新点时取最大值 , 但是要小于所用的mid , 似乎是没有堆优化的dijkstra算法
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long int
inline int read() {
int ans = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
ans = ans * 10 + ch - '0';
ch = getchar();
}
return ans * f;
}
struct Edge {
int v,w;
};
const int N =2e5+10;
int b[N];
vector<Edge> ed[N];
int n,m;
int t;
bool check(int mid) {
vector<int> best(n+1,0);
for (int i = 1; i<= n; i++) {
if (i > 1 && best[i] == 0)
continue;
best[i] += b[i];
best[i] = min(best[i],mid);
for (auto e : ed[i]) {
if (e.w <= best[i]) {
best[e.v] = max(best[e.v],best[i]);
}
}
}
return best[n] > 0;
}
void solve() {
n =read(),m=read();
t = n;
for (int i = 1; i <= n; i++) {
b[i] =read();
ed[i].clear();
}
for (int i = 1; i <= m; i++) {
int s= read(),t=read(),w=read();
ed[s].push_back({t,w});
}
if (!check(1e9+10)) {
cout<<"-1\n";
return ;
}
int l = 0, r= 1e9+10;
int mid;
while (l + 1 < r) {
mid = l + r>>1;
if (check(mid)) {
r = mid;
}
else l = mid;
}
cout<<(r==1e9+10?-1:r)<<"\n";
}
signed main() {
int t= read();
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号