QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#226788#7580. Milk Candy8BQube#AC ✓108ms3552kbC++204.3kb2023-10-26 16:19:092023-10-26 16:19:10

Judging History

你现在查看的是最新测评结果

  • [2023-10-26 16:19:10]
  • 评测
  • 测评结果:AC
  • 用时:108ms
  • 内存:3552kb
  • [2023-10-26 16:19:09]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
#define X first
#define Y second
#define pb push_back
#define SZ(a) ((int)a.size())
#define ALL(v) v.begin(), v.end()

struct Edge {
    int u, v, w, c;  
} edges[85];

const int INF = 1e9;
int choose[85], tag[85], num[85], bound[85], boss[85];
vector<int> G[85];
pii dis[85];
int frm[85], inq[85];

int finds(int x) {
    if (x == boss[x]) return x;
    return boss[x] = finds(boss[x]);
}

bool Union(int x, int y) {
    x = finds(x), y = finds(y);
    if (x == y) return false;
    boss[x] = y;
    return true;
}

int cal(int n, int m) {
    int conn = n;
    iota(boss, boss + n, 0);
    for (int i = 0; i < m; ++i)
        if (!choose[i])
            conn -= Union(edges[i].u, edges[i].v);
    return conn;
}

int SPFA(int n) {
    fill_n(dis, n, make_pair(-INF, INF)), fill_n(inq, n, 0), fill_n(frm, n, -1);
    queue<int> q;
    auto relax = [&](int u, pii d, int f) {
        if (dis[u] < d) {
            dis[u] = d, frm[u] = f;
            if (!inq[u]) inq[u] = 1, q.push(u);
        }
    };
    auto wei = [&](int x) {
        if (choose[x]) return -edges[x].w;
        return edges[x].w;
    };
    for (int i = 0; i < n; ++i)
        if (tag[i] & 1)
            relax(i, pii(wei(i), 0), -1);
    while (!q.empty()) {
        int u = q.front();
        q.pop(), inq[u] = 0;
        for (int e : G[u]) {
            pii td = dis[u];
            td.X += wei(e);
            td.Y -= 1;
            relax(e, td, u);
        }
    }
    int mi = -1;
    for (int i = 0; i < n; ++i)
        if ((tag[i] & 2) && dis[i].X != -INF && (mi == -1 || dis[mi].X < dis[i].X))
            mi = i;
    return mi;
}

void solve() {
    /*memset(choose, 0, sizeof choose);
    memset(tag, 0, sizeof tag);
    memset(num, 0, sizeof num);
    memset(bound, 0, sizeof bound);
    memset(boss, 0, sizeof boss);
    memset(dis, 0, sizeof dis);
    memset(frm, 0, sizeof frm);
    memset(inq, 0, sizeof inq);
    memset(edges, 0, sizeof edges);
    for (int i = 0; i < 85; ++i)
        G[i].clear();*/
    int n, m, tp = 0, sum = 0, total = 0;
    cin >> n >> m;
    for (int i = 1; i <= m; ++i) {
        int k;
        cin >> k >> bound[i];
        bound[i] = k - bound[i];
        sum += bound[i];
        num[i] = 0;
        while (k--) {
            cin >> edges[tp].u >> edges[tp].v >> edges[tp].w;
            edges[tp].c = i, --edges[tp].u;
            choose[tp] = 0, total += edges[tp].w;
            ++tp;
        }
    }

    auto checkI1 = [&]() {
        return cal(n + 1, tp) == 1;
    };

    auto altI1 = [&](int rmv, int add) {
        assert((rmv == -1 || choose[rmv] == 1) && choose[add] == 0);
        if (rmv >= 0) choose[rmv] = 0;
        choose[add] = 1;
        int flag = checkI1();
        if (rmv >= 0) choose[rmv] = 1;
        choose[add] = 0;
        return flag;
    };

    auto altI2 = [&](int rmv, int add) {
        assert((rmv == -1 || choose[rmv] == 1) && choose[add] == 0);
        int f = num[edges[add].c] + 1;
        if (rmv >= 0 && edges[rmv].c == edges[add].c)
            --f;
        return f <= bound[edges[add].c];
    };

    auto flip = [&](int x) {
        if (choose[x]) --num[edges[x].c];
        else ++num[edges[x].c];
        assert(num[edges[x].c] <= bound[edges[x].c]);
        choose[x] ^= 1;
    };

    if (!checkI1()) {
        cout << "-1\n";
        return;
    }

    int cur = 0, ans = 0;
    while (cur < sum) {
        for (int i = 0; i < tp; ++i)
            G[i].clear();
        for (int i = 0; i < tp; ++i) {
            tag[i] = 0;
            if (!choose[i] && altI1(-1, i)) tag[i] |= 1;
            if (!choose[i] && altI2(-1, i)) tag[i] |= 2;
        }
        for (int i = 0; i < tp; ++i)
            if (choose[i])
                for (int j = 0; j < tp; ++j)
                    if (!choose[j]) {
                        if (altI1(i, j)) G[i].pb(j);
                        if (altI2(i, j)) G[j].pb(i);
                    }
        int res = SPFA(tp);
        if (res == -1) break;
        ans += dis[res].X;
        while (res != -1) {
            flip(res);
            res = frm[res];
        }
        ++cur;
    }
    if (cur < sum) cout << "-1\n";
    else cout << total - ans << "\n";
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3536kb

input:

2
2 2
1 1
1 2 1
3 2
1 1 10
2 2 100
1 2 1000
2 2
1 1
1 1 1
1 1
1 1 2

output:

111
-1

result:

ok 2 number(s): "111 -1"

Test #2:

score: 0
Accepted
time: 108ms
memory: 3552kb

input:

10
50 55
1 1
1 1 829226
1 1
2 2 485572
1 1
3 3 541135
1 1
4 4 683672
1 1
5 5 221134
1 1
6 6 589289
1 1
7 7 853944
1 1
8 8 463334
2 1
9 9 212920
24 34 4065
2 2
10 10 920920
40 43 559059
1 1
11 11 467880
1 1
12 12 561361
2 1
13 13 218407
29 48 226199
1 1
14 14 353783
1 1
15 15 875637
1 1
16 16 122290
...

output:

29640398
40230474
-1
12149117
9430424
13935806
14440341
8331917
15753760
16573955

result:

ok 10 numbers