QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#839333#873. Königsberg BridgesohwphilAC ✓1141ms391628kbC++176.1kb2025-01-01 17:08:412025-01-01 17:08:41

Judging History

This is the latest submission verdict.

  • [2025-01-01 17:08:41]
  • Judged
  • Verdict: AC
  • Time: 1141ms
  • Memory: 391628kb
  • [2025-01-01 17:08:41]
  • Submitted

answer

#include <bits/stdc++.h>
#include <array>
using namespace std;

typedef long long ll;

// DFS Tree
// Finds bridges, articulation points, and biconnected components
struct DFSTree {
    // size of graph
    int N;
    vector<vector<int>> adj, tree_children, back_edges;
    vector<int> tree_parent;
    vector<int> depth, dp;

    vector<pair<int, int>> bridges;
    vector<int> articulation_points;
    vector<vector<pair<int, int>>> biconnected_components;
    stack<pair<int, int>> edge_stack;

    DFSTree() { DFSTree(0); }
    DFSTree(int _N) : N(_N), adj(_N + 1), tree_children(_N + 1), back_edges(_N + 1), tree_parent(_N + 1, -1), depth(_N + 1, -1), dp(_N + 1) {}

    void add_edge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    void dfs(int curr_node, int curr_depth = 0) {
        depth[curr_node] = curr_depth;
        int cnt = 0;
        for (int next_node : adj[curr_node]) {
            if (next_node == tree_parent[curr_node]) {
                continue;
            }
            if (depth[next_node] == -1) {
                edge_stack.push(make_pair(min(curr_node, next_node), max(curr_node, next_node)));
                tree_children[curr_node].push_back(next_node);
                tree_parent[next_node] = curr_node;
                int curr_dp = dp[curr_node];
                dfs(next_node, curr_depth + 1);
                dp[curr_node] += dp[next_node];
                if (dp[curr_node] == curr_dp) {
                    ++cnt;
                    // separate biconnected component
                    vector<pair<int, int>> component;
                    auto reference_pair = make_pair(min(curr_node, next_node), max(curr_node, next_node));
                    while (true) {
                        auto edge = edge_stack.top();
                        edge_stack.pop();
                        component.push_back(edge);
                        if (edge == reference_pair) {
                            break;
                        }
                    }
                    biconnected_components.push_back(component);
                }
            }
            else if (depth[next_node] < depth[curr_node]) {
                edge_stack.push(make_pair(min(curr_node, next_node), max(curr_node, next_node)));
                back_edges[curr_node].push_back(next_node);
                ++dp[next_node];
                --dp[curr_node];
            }
        }
        if (tree_parent[curr_node] != -1 && dp[curr_node] == 0) {
            bridges.push_back({min(curr_node, tree_parent[curr_node]), max(curr_node, tree_parent[curr_node])});
        }
        if ((tree_parent[curr_node] == -1 && cnt >= 2) || (tree_parent[curr_node] != -1 && cnt >= 1)) {
            articulation_points.push_back(curr_node);
        }
    }

    void compute() {
        for (int i = 1; i <= N; i++) {
            if (depth[i] == -1) {
                dfs(i, 0);
            }
        }
        sort(bridges.begin(), bridges.end());
        sort(articulation_points.begin(), articulation_points.end());
    }
};

// Disjoint set union
struct DSU {
    // size of graph
    int N;
    vector<int> rank;

    DSU() { DSU(0); }
    DSU(int _N) : N(_N), rank(_N + 1, -1) {}

    int get_parent(int node) {
        if (rank[node] < 0) {
            return node;
        }
        return rank[node] = get_parent(rank[node]);
    }

    void merge(int node1, int node2) {
        node1 = get_parent(node1);
        node2 = get_parent(node2);

        if (node1 == node2) return;

        if (-rank[node1] < -rank[node2]) swap(node1, node2);
        rank[node1] += rank[node2];
        rank[node2] = node1;
    }
};

int N, M;

DFSTree tree;
DSU dsu;

vector<int> bridge_dp;

set<pair<int, int>> multiple_edges;
map<pair<int, int>, int> counter;

vector<int> visited;

int ans;

int dfs_dp(int node, int& curr_ans) {
    // bridge_dp[node] = (tree.tree_parent[node] != -1 && tree.dp[node] == 0);
    // if (tree.tree_parent[node] != -1 && multiple_edges.find({min(node, tree.tree_parent[node]), max(node, tree.tree_parent[node])}) != multiple_edges.end()) {
    //     bridge_dp[node] = 0;
    // }
    visited[node] = true;
    vector<int> values;
    for (auto child : tree.tree_children[node]) {
        int curr_val = dfs_dp(child, curr_ans);
        if (multiple_edges.find({min(node, child), max(node, child)}) == multiple_edges.end() && tree.dp[child] == 0) {
            ++curr_val;
        }
        values.push_back(curr_val);
    }
    sort(values.begin(), values.end());
    if (values.size() == 0) {
        return 0;
    }
    if (values.size() == 1) {
        curr_ans = max(values[0], curr_ans);
    }
    if (values.size() >= 2) {
        curr_ans = max(values[values.size() - 2] + values[values.size() - 1], curr_ans);
    }
    return values[values.size() - 1];
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin >> N >> M;

    bridge_dp.resize(N + 1);
    visited.resize(N + 1);
    dsu = DSU(N);
    tree = DFSTree(N);

    for (int i = 0; i < M; ++i) {
        int u, v;
        cin >> u >> v;
        if (u == v) continue;
        ++u; ++v;
        if (u > v) swap(u, v);
        // tree.add_edge(u, v);
        // edge_sets.insert({u, v});
        ++counter[{u, v}];
        if (counter[{u, v}] == 2) {
            multiple_edges.insert({u, v});
        }
    }
    
    for (auto [p, c] : counter) {
        auto [u, v] = p;
        tree.add_edge(u, v);
        dsu.merge(u, v);
    }

    vector<int> parents;
    for (int i = 1; i <= N; ++i) {
        parents.push_back(dsu.get_parent(i));
    }

    sort(parents.begin(), parents.end());
    parents.erase(unique(parents.begin(), parents.end()), parents.end());


    tree.compute();

    for (int i = 1; i <= N; ++i) {
        if (!visited[i]) {
            int curr_ans = 0;
            dfs_dp(i, curr_ans);
            ans += curr_ans;
        }
    }

    ans += parents.size() - 1;

    cout << ans << "\n";

    return 0;
}

详细

Test #1:

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

input:

4 3
0 1
1 2
2 0

output:

1

result:

ok 1 number(s): "1"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3560kb

input:

4 2
0 1
1 2

output:

3

result:

ok 1 number(s): "3"

Test #3:

score: 0
Accepted
time: 609ms
memory: 169932kb

input:

266912 867557
0 31522
0 174162
0 4209
1 58647
1 5722
1 24762
1 258525
1 148028
1 72989
1 170812
1 260494
1 86533
1 212481
2 143457
2 47080
2 72841
2 113512
2 64754
2 231454
3 220536
3 97144
3 183508
3 177546
3 149060
3 140197
3 87427
3 169096
4 132318
4 67337
4 23014
4 34254
4 11851
4 12558
4 49756
...

output:

380

result:

ok 1 number(s): "380"

Test #4:

score: 0
Accepted
time: 454ms
memory: 126744kb

input:

92162 903746
0 78341
0 30101
0 86910
0 71281
0 66038
0 58991
0 27261
0 12794
0 44202
0 27063
0 8617
0 1463
0 48097
0 24219
0 51184
0 42335
0 20179
0 79826
0 29670
0 121
0 80004
0 22547
0 54055
0 80647
0 20967
0 7230
0 20852
0 67815
0 63277
0 61650
1 24614
1 60787
1 78668
1 73795
1 36239
1 90410
1 71...

output:

0

result:

ok 1 number(s): "0"

Test #5:

score: 0
Accepted
time: 23ms
memory: 98156kb

input:

946158 0

output:

946157

result:

ok 1 number(s): "946157"

Test #6:

score: 0
Accepted
time: 47ms
memory: 76412kb

input:

717331 671
277 661428
388 696195
2457 576086
2926 555369
2959 191594
4142 432000
4312 309773
4858 471165
4886 682026
5569 403920
5620 470329
6027 546706
6049 179350
6596 471181
6792 416677
7466 628061
7648 378219
7650 560432
7660 55602
7973 18975
8076 121285
8123 172484
8325 202734
8570 501604
8904 ...

output:

717330

result:

ok 1 number(s): "717330"

Test #7:

score: 0
Accepted
time: 1141ms
memory: 301380kb

input:

1000000 1000000
0 168067
0 116972
1 776624
1 327773
1 145060
2 14506
2 181311
2 431159
2 652430
3 173884
4 394795
4 172555
5 494172
5 945490
7 595196
7 593371
7 358866
8 860794
9 598459
10 505821
10 41753
10 880384
11 74592
11 715116
11 659129
12 977041
12 807365
12 952349
13 844571
13 154379
15 185...

output:

200542

result:

ok 1 number(s): "200542"

Test #8:

score: 0
Accepted
time: 1132ms
memory: 303656kb

input:

1000000 999999
1 412610
2 712889
2 254970
2 803563
3 678225
6 294090
6 662272
7 593625
7 444343
7 348966
7 168525
8 273575
8 486405
9 644268
9 321394
9 223587
11 719799
11 547678
11 742807
11 332536
12 260338
13 995176
14 234723
14 785909
15 406384
15 636469
16 388652
16 528991
17 741822
18 78605
19...

output:

201011

result:

ok 1 number(s): "201011"

Test #9:

score: 0
Accepted
time: 62ms
memory: 104088kb

input:

1000000 8936
62 728171
75 810657
186 344905
204 186449
253 441452
271 371090
292 948549
306 595932
315 901739
390 621170
396 287021
473 437138
494 530383
513 588605
527 23089
531 768891
567 189841
600 335182
693 723411
731 521138
745 696157
877 168905
925 902019
997 668395
1025 968824
1152 56167
119...

output:

999999

result:

ok 1 number(s): "999999"

Test #10:

score: 0
Accepted
time: 597ms
memory: 273680kb

input:

688670 688669
0 1
1 2
1 3
1 4
3 5
4 10
5 6
6 7
7 8
8 9
9 11
9 12
11 13
11 14
14 15
14 17
15 16
16 18
16 19
18 24
18 26
19 20
19 22
20 21
21 23
21 27
23 25
23 28
25 29
25 30
29 31
29 36
31 32
31 34
32 33
33 35
34 39
35 37
37 38
37 41
38 40
40 42
40 43
42 44
44 45
44 48
45 46
46 47
46 49
46 51
47 50
4...

output:

398561

result:

ok 1 number(s): "398561"

Test #11:

score: 0
Accepted
time: 895ms
memory: 391628kb

input:

1000000 999999
0 1
0 2
1 3
1 7
2 5
3 4
4 6
6 8
7 9
8 10
8 11
8 12
12 13
13 14
14 15
15 16
16 17
16 18
16 19
17 22
18 20
20 21
21 23
23 24
24 25
25 26
25 27
25 28
26 31
27 29
29 30
31 32
32 33
32 40
33 34
34 35
34 39
35 36
36 37
37 38
38 41
41 42
41 43
42 44
44 45
44 46
45 47
47 48
48 49
48 51
49 50
...

output:

578343

result:

ok 1 number(s): "578343"