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;
}

posted @ 2025-05-26 19:40  Guaninf  阅读(13)  评论(0)    收藏  举报