QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#607552#8941. Even or Odd Spanning Treexing4cML 0ms24120kbC++144.5kb2024-10-03 15:17:472024-10-03 15:17:47

Judging History

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

  • [2024-10-03 15:17:47]
  • 评测
  • 测评结果:ML
  • 用时:0ms
  • 内存:24120kb
  • [2024-10-03 15:17:47]
  • 提交

answer

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;
#define int long long
const int N = 2e5 + 7;
const int M = 5e5 + 7;
const int INF = 2e18l;
int n = 0, m = 0;
struct Line {
    int id, u, v, w;
} e[M];

bool cmp(Line a, Line b) {
    return a.w < b.w;
}

int dad[N] = {0};
bool chosen[M] = {false};
int ans[2];

vector<pair<int, int>> G[N];
int fa[N], depth[N] = {0}, heavy[N];
int siz[N], pt[N];
int rnk[N], top[N];
int cnt = 0, dfn[N];

void clear() {
    for (int i = 1; i <= m; i++) {
        e[i] = {0, 0, 0, 0};
    }
    ans[0] = ans[1] = 0;
    cnt = 0;
    for (int i = 1; i <= n; i++) {
        dad[i] = 0;
        chosen[i] = false;
        G[i].clear();
        fa[i] = depth[i] = heavy[i] = 0;
        siz[i] = pt[i] = 0;
        rnk[i] = top[i] = 0;
        dfn[i] = 0;
    }
}

void reset() {
    for (int i = 1; i <= n; i++) {
        dad[i] = i;
        siz[i] = 1;
    }
}

int find(int x) {
    if (dad[x] == x)return x;
    return dad[x] = find(dad[x]);
}

void merge(int a, int b) {
    dad[find(a)] = find(b);
}

void Dfs1(int u, int from) {
    siz[u] = 1;
    fa[u] = from;
    depth[u] = depth[from] + 1;
    for (auto [to, w]: G[u]) {
        if (to == from)continue;
        Dfs1(to, u);
        siz[u] += siz[to];
        pt[to] = w;
    }
    int big = 0;
    for (auto [to, w]: G[u]) {
        if (to == from)continue;
        if (siz[to] >= big) {
            big = siz[to];
            heavy[u] = to;
        }
    }
}

void Dfs2(int u) {
    if (!u)return;
    dfn[u] = ++cnt;
    rnk[cnt] = u;

    if (heavy[fa[u]] == u)top[u] = top[fa[u]];
    else top[u] = u; //判断u是否为新的重链头

    Dfs2(heavy[u]);

    for (auto [to, w]: G[u]) {
        if (to == fa[u] || to == heavy[u])continue;
        Dfs2(to);
    }
}


int Logn[N];
int maxn[2][N][22];

void BuildST() {
    for (int i = 1; i <= n; i++) {
        int val = pt[rnk[i]];
        maxn[val & 1][i][0] = val;
        maxn[1 - (val & 1)][i][0] = -1;
    }

    for (int j = 1; j <= 21; j++) {
        for (int i = 1; i <= n; i++) {
            if (i + (1 << j) - 1 > n)break;
            maxn[0][i][j] = max(maxn[0][i][j - 1], maxn[0][i + (1 << (j - 1))][j - 1]);
            maxn[1][i][j] = max(maxn[1][i][j - 1], maxn[1][i + (1 << (j - 1))][j - 1]);
        }
    }
}

int QueryST(int type, int l, int r) {
    if (l > r)swap(l, r);
    int s = Logn[r - l + 1];
    return max(maxn[type][l][s], maxn[type][r - (1 << s) + 1][s]);
}

int QueryPath(int type, int u, int v) {
    int res = -1;
    while (top[u] != top[v]) {
        if (depth[top[u]] < depth[top[v]])swap(u, v);
        res = max(res, QueryST(type, dfn[u], dfn[top[u]]));
        u = fa[top[u]];
    }
    if (depth[u] > depth[v])swap(u, v);
    if (u != v)res = max(res, QueryST(type, dfn[v], dfn[u] + 1));
    return res;
}

void solve() {
    cin >> n >> m;
    reset();
    for (int i = 1; i <= m; i++) {
        cin >> e[i].u >> e[i].v >> e[i].w;
        e[i].id = i;
    }

    sort(e + 1, e + 1 + m, cmp);
    int res1 = 0;
    int line_cnt = 0;
    for (int i = 1; i <= m; i++) {
        int u = e[i].u, v = e[i].v;
        if (find(u) == find(v))continue;
        res1 += e[i].w;
        chosen[e[i].id] = true;
        merge(u, v);
        line_cnt++;
    }

    if (line_cnt != n - 1) {
        cout << -1 << " " << -1 << endl;
        clear();
        return;
    }

    ans[res1 & 1] = res1;
    ans[1 - (res1 & 1)] = INF;
    int ind = 1 - (res1 & 1);
    for (int i = 1; i <= m; i++) {
        if (!chosen[e[i].id])continue;
        int u = e[i].u, v = e[i].v, w = e[i].w;
        G[u].emplace_back(v, w);
        G[v].emplace_back(u, w);
    }

    Dfs1(1, 0);
    Dfs2(1);
    BuildST();

    for (int i = 1; i <= m; i++) {
        if (chosen[e[i].id])continue;
        int u = e[i].u, v = e[i].v, w = e[i].w;
        int res = QueryPath(1 - (w & 1), u, v);
        if (res == -1 || res == INF)continue;
        ans[ind] = min(ans[ind], res1 - res + w);
    }

    if (ans[ind] == INF) {
        ans[ind] = -1;
    }
    cout << ans[0] << " " << ans[1] << endl;
    clear();
}

void pre() {
    Logn[1] = 0;
    Logn[2] = 1;
    for (int i = 3; i < N; i++) {
        Logn[i] = Logn[i / 2] + 1;
    }
}

signed main() {
    //  freopen("D:\\Development_Software\\CLion\\CLionProjects\\Test\\in", "r", stdin);
    ios::sync_with_stdio(false);
    pre();
    int T = 1;
    cin >> T;
    while (T--) solve();
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

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

input:

3
2 1
1 2 5
3 1
1 3 1
4 4
1 2 1
1 3 1
1 4 1
2 4 2

output:

-1 5
-1 -1
4 3

result:

ok 6 numbers

Test #2:

score: -100
Memory Limit Exceeded

input:

10000
16 50
1 2 649251632
2 3 605963017
3 4 897721528
4 5 82446151
5 6 917109168
6 7 79647183
7 8 278566178
7 9 573504723
3 10 679859251
8 11 563113083
1 12 843328546
10 13 594049160
11 14 997882839
7 15 569431750
2 16 244494799
16 7 960172373
13 4 317888322
13 3 446883598
9 3 678142319
5 8 43208692...

output:

3140067932 3159441841

result: