2109D Div. 2 Round 1025

题意

给定若干个元素 , 判断跨过其中若干元素的和数量条边是否可以从一个图的源点到达其他点

思路

和某个洛谷的题很像 , 首先单源最短路 , 且无边权 , 所以用bfs , 然后考虑更新到每个点的奇数路径长度和偶数路径长度即可

代码


#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;
}
const int N = 2e5+10;
int b[N];
vector<int> ed[N];
int idx;
int odd[N],even[N];
int n,m,l;
typedef pair<int,int> PII;
void bfs() {
    for (int i =1; i<= n;i++) {
        odd[i] =2e9+10;
        even[i] =2e9+10;
    }
    queue<PII> q;
    q.push({1,0});
    even[1] = 0;
    while (q.size()) {
        auto [u,p] = q.front();q.pop();
        for (auto e : ed[u]) {
            if (p&1) {
                //even
                if (even[e] > p + 1) {
                    even[e] = p+1;
                    q.push({e,p+1});
                }
            }
            else {
                if (!(p&1)) {
                    //odd
                    if (odd[e] > p+1) {
                        odd[e] = p+1;
                        q.push({e,p+1});
                    }
                }
            }
        }
    }
}
void solve() {
    int sum=0,oddsum=0,evensum =0;
    idx=0;
    n=read(),m=read(),l=read();
    for (int i = 1; i<= l; i++) {
        int tmp=read();
        if (!(tmp&1))
            sum+=tmp;
        else
           b[++idx] = tmp;
    }
    for (int i = 1; i<=m;i++) {
        int u=read(),v=read();
        ed[u].push_back(v);
        ed[v].push_back(u);
    }
    sort(b+1,b+1+idx);
    reverse(b+1,b+1+idx);
    for (int i =1; i<= idx; i++) {
        if (i!= idx) {
            oddsum += b[i];
            evensum += b[i];
        }
        else {
            oddsum += idx&1?b[idx]:0;
            evensum += idx&1?0:b[idx];
        }
    }
    if (idx)
        oddsum += sum;
    evensum += sum;
    bfs();
    for (int i =1;i<=n;i++) {
        if (even[i] <= evensum || odd[i] <= oddsum) {
            cout<<1;
        }
        else {
            cout<<0;
        }
    }
    cout<<"\n";
    for (int i = 1; i<= n;i++) {
        ed[i].clear();
    }
}
signed main() {
    int t;
    cin>>t;
    while (t--) solve();
    return 0;
}
posted @ 2025-05-18 23:57  Guaninf  阅读(9)  评论(0)    收藏  举报