codeforce 1700-1900

zhujio發表於2024-03-06

3.6

Lonely Mountain Dungeons

算貢獻算了半天還錯了, 這種採用容斥可以減少細節處理, 程式碼註釋有

codeforce 1700-1900
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
typedef long long ll;

void solve() {
    int n, b, x; cin >> n >> b >> x;
    // cout << n << b << x << endl;
    vector<int> a(n + 1);
    map<int, int> mp;
    for (int i = 1; i <= n; i++) cin >> a[i], mp[a[i]]++;
    int maxn = *max_element(a.begin() + 1, a.begin() + 1 + n), ans = 0;

    auto calc = [&](int x, int d) {
        // x 代表人數, d 代表組數
        // 假設全排成一排( x 個人到 x 組都是一個)
        int ans = x * (x - 1) / 2;
        // t 代表 x 人分為 d 組,每組都有的共同人數
        int t = x / d;
        // del代表有 del 組多出來一個人
        int del = x % d;
        // 1. 那麼對於這些人數,我們組內沒有貢獻的,我們容斥需要減去這些貢獻(C(t, 2))
        ans -= d * t * (t - 1) / 2;
        // 2. 有 del 組多出來一個人, 對於多出來的那個人,我們會減少的貢獻是他組內的 t 個人
        ans -= del * t;
        return ans * b;
    };

    for (int i = 1; i <= maxn; i++) {
        int sum = -(i - 1) * x;
        // cout << "TEST " << i << endl;
        for (auto [id, v] : mp) {
            if (id <= i) {
                // cout << id << endl;
                sum += id * (id - 1) / 2 * b * v;
                continue;
            }
            sum += v * calc(id, i);
            // cout << v * calc(id, i) << ' ' << id << endl;
        }
        ans = max(ans, sum);
    }
    cout << ans << endl;
}   

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

    int T = 1; cin >> T;
    while (T--) solve();
    // solve();    

    return 0;
}
View Code

Microcycle

我們取一顆最大生成樹, 那麼一條非樹邊會產生一個環, 我們找到這樣一條權值最小的邊去 dfs

codeforce 1700-1900
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
typedef long long ll;

const int N = 2e5 + 100;

struct node {
    int x, y, v;
} e[N];

bool cmp(node a, node b) {
    return a.v > b.v;
}

vector<int> g[N];

int fa[N], vis[N];
int find(int x) {
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}

vector<int> cir;
void dfs(int x, int t) {
    vis[x] = 1;
    cir.push_back(x);
    if (x == t) {
        cout << cir.size() << endl;
        for (auto i : cir) cout << i << ' ';
        cout << endl;
        return;
    }
    for (auto y : g[x]) {
        if (!vis[y]) dfs(y, t);
    }
    cir.pop_back();
}

void solve() {
    int n, m; cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int x, y, v; cin >> x >> y >> v;
        e[i] = {x, y, v};
    }
    cir.clear();
    for (int i = 1; i <= n; i++) fa[i] = i, vis[i] = 0, g[i].clear();
    sort(e + 1, e + 1 + m, cmp);
    int minn = INT_MAX / 2, id;
    for (int i = 1; i <= m; i++) {
        auto [x, y, v] = e[i];
        int fx = find(x), fy = find(y);
        if (fx != fy) {
            fa[fx] = fy;
        } else {
            minn = min(minn, v);
            id = i;
        }
    }
    for (int i = 1; i <= m; i++) {
        if (i != id) {
            auto [x, y, v] = e[i];
            g[x].push_back(y);
            g[y].push_back(x);   
        }
    }

    cout << minn << ' ';
    dfs(e[id].x, e[id].y);
}   


signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

    int T = 1; cin >> T;
    while (T--) solve();

    return 0;
}
View Code