808F - Card Game - CodeForces Solution


binary search flows graphs *2400

Please click on ads to support us..

C++ Code:

#include "bits/stdc++.h"
using namespace std;

#ifdef LOCAL
#include "debug.h"
#else
#define debug(...)
#endif

using ll = long long;
using pii = pair<int, int>;

#define F first
#define S second
#define sz(x) (int)((x).size())
#define all(x) (x).begin(), (x).end()

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll get_rand(ll l, ll r) {
    assert(l <= r);
    return uniform_int_distribution<ll> (l, r)(rng);
}

const ll INF = 1e18;
struct Dinic{
    const static bool SCALING = false; // scaling = EV log(max C) with larger constant
    ll lim = 1;

    struct Edge{
        int u, v;
        ll cap, flow;
    };

    int n, s, t;
    vector<int> level, ptr;
    vector<Edge> e;
    vector<vector<int>> g;

    Dinic(int _n) : n(_n), level(_n), ptr(_n), g(_n){
        e.clear();
        for(int i = 0; i < n; ++i){
            ptr[i] = 0;
            g[i].clear();
        }
    }

    void add_edge(int u, int v, ll c){
        debug(u, v, c);
        g[u].push_back(sz(e));
        e.push_back({u, v, c, 0});
        g[v].push_back(sz(e));
        e.push_back({v, u, 0, 0});
    }

    ll get_max_flow(int _s, int _t){
        s = _s, t = _t;
        ll flow = 0;
        for(lim = SCALING ? (1 << 30) : 1; lim > 0; lim >>= 1){
            while(1){
                if(!bfs()) break;
                fill(all(ptr), 0);
                while(ll pushed = dfs(s, INF))
                    flow += pushed;
            }
        }
        return flow;
    }

private:
    bool bfs(){
        queue<int> q;
        q.push(s);
        fill(all(level), -1);
        level[s] = 0;
        while(!q.empty()){
            int u = q.front();
            q.pop();
            for(int id : g[u]){
                if(e[id].cap - e[id].flow < 1)
                    continue;
                if(level[e[id].v] != -1)
                    continue;
                if(SCALING and e[id].cap - e[id].flow < lim)
                    continue;
                level[e[id].v] = level[u] + 1;
                q.push(e[id].v);
            }
        }
        return level[t] != -1;
    }

    ll dfs(int u, ll flow){
        if(!flow)
            return 0;
        if(u == t)
            return flow;
        for(; ptr[u] < sz(g[u]); ++ptr[u]){
            int id = g[u][ptr[u]], to = e[id].v;
            if(level[to] != level[u] + 1)
                continue;
            ll pushed = dfs(to, min(flow, e[id].cap - e[id].flow));
            if(pushed){
                e[id].flow += pushed;
                e[id ^ 1].flow -= pushed;
                return pushed;
            }
        }
        return 0;
    }
};

const int N = 103;

struct Card{
    int p, c, l;
} card[N];

int n, k;

bool is_prime(ll x){
    if(x <= 1)
        return 0;
    for(ll i = 2; i * i <= x; ++i)
        if(x % i == 0)
            return 0;
    return 1;
}

bool check(int level){
    vector<Card> dak;
    int total = 0;
    int troll = -1;

    for(int i = 1; i <= n; ++i){
        if(card[i].l > level)
            continue;
        if(card[i].c == 1){
            if(troll == -1 or card[troll].p < card[i].p) troll = i;
        }
        else{
            debug(card[i].c);
            dak.push_back(card[i]);
            total += card[i].p;
        }
    }

    if(troll != -1){
        total += card[troll].p;
        dak.push_back(card[troll]);
    }

    Dinic dinic(sz(dak) + 2);
    int st = sz(dak), en = sz(dak) + 1;

    for(int i = 0; i < sz(dak); ++i){
        if(dak[i].c & 1){
            dinic.add_edge(st, i, dak[i].p);
            for(int j = 0; j < sz(dak); ++j){
                if(i == j)
                    continue;
                if(is_prime(dak[i].c + dak[j].c))
                    dinic.add_edge(i, j, INF);
            }
        }
        else
            dinic.add_edge(i, en, dak[i].p);
    }

    int res = total - dinic.get_max_flow(st, en);

    debug(level, res);

    return res >= k;
}

void solve(){
    cin >> n >> k;
    for(int i = 1; i <= n; ++i)
        cin >> card[i].p >> card[i].c >> card[i].l;
    int l = 1, r = n, res = -1;
    while(l <= r){
        int mid = (l + r) / 2;
        if(check(mid)){
            res = mid;
            r = mid - 1;
        }
        else
            l = mid + 1;
    }
    cout << res;
}

int32_t main() {
    cin.tie(nullptr)->sync_with_stdio(0);
    #define task "troll"
    if(fopen(task".inp", "r")){
        freopen(task".inp", "r", stdin);
        freopen(task".out", "w", stdout);
    }
    int test = 1;
//    cin >> test;
    for(int i = 1; i <= test; ++i){
//        cout << "Case #" << i << ": ";
        solve();
    }
    #ifdef LOCAL
        cerr << "\n[Time]: " << 1000.0 * clock() / CLOCKS_PER_SEC << " ms.\n";
    #endif
    return 0;
}


Comments

Submit
0 Comments
More Questions

1691B - Shoe Shuffling
1706A - Another String Minimization Problem
1695B - Circle Game
1702B - Polycarp Writes a String from Memory
1701A - Grass Field
489C - Given Length and Sum of Digits
886B - Vlad and Cafes
915A - Garden
356A - Knight Tournament
1330A - Dreamoon and Ranking Collection
1692B - All Distinct
1156C - Match Points
1675A - Food for Animals
1328C - Ternary XOR
1689A - Lex String
1708B - Difference of GCDs
863A - Quasi-palindrome
1478A - Nezzar and Colorful Balls
1581B - Diameter of Graph
404A - Valera and X
908A - New Year and Counting Cards
146A - Lucky Ticket
1594C - Make Them Equal
1676A - Lucky
1700B - Palindromic Numbers
702C - Cellular Network
1672C - Unequal Array
1706C - Qpwoeirut And The City
1697A - Parkway Walk
1505B - DMCA