树上差分WA on 23 求助
  • 板块CF19E Fairy
  • 楼主Z1qqurat
  • 当前回复3
  • 已保存回复3
  • 发布时间2023/6/27 21:45
  • 上次更新2023/11/3 12:17:11
查看原帖
树上差分WA on 23 求助
483928
Z1qqurat楼主2023/6/27 21:45

大体思路是第一篇题解,我认为我连通性处理得很正确了。有注释,求调

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#define ll long long
#define pii pair<int, int>
using namespace std;
const int N = 2e4 + 5;
int n, m, setid[N], fa[N], dep[N], diff[N], cnt, w[N];
bool ans[N], vis[N];
vector <pii> G[N];
struct Ed{
    int u, v;
    bool pass; //passable
}e[N];

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

void merge(int x, int y) {
    setid[find(x)] = find(y);
    return ;
}

void Spanning() { //构建一棵生成树,并且标出树边和非树边
    for (int i = 1; i <= n; ++i) setid[i] = i;
    for (int i = 1; i <= m; ++i) {
        int u = find(e[i].u), v = find(e[i].v);
        if(u != v) {
            G[e[i].u].push_back(make_pair(e[i].v, i));
            G[e[i].v].push_back(make_pair(e[i].u, i));
            e[i].pass = 1;
            setid[u] = v;
        }
    }
    return ;
}

void dfs(int u) { //计算树上每个点的父亲节点,深度
    vis[u] = 1;
    for (int i = 0; i < G[u].size(); ++i) {
        int v = G[u][i].first;
        if(v == fa[u]) continue;
        fa[v] = u, dep[v] = dep[u] + 1;
        dfs(v);
    }
    return ;
}

void modify(int u, int v, int val) { //树上差分:将u->v路径上所有边权值+val
    if(dep[v] > dep[u]) swap(u, v);
    diff[u] += val, diff[v] -= val;
    return ;
}

int df5(int u, int eid) { //求出边(u, fa[u]) ,即编号为eid的边的边权
    vis[u] = 1;
    w[eid] = diff[u];
    for (int i = 0; i < G[u].size(); ++i) {
        int v = G[u][i].first;
        if(v == fa[u]) continue;
        w[eid] += df5(v, G[u][i].second);
    }
    return w[eid];
}

void Extend() {
    int sp = 0;
    for (int i = 1; i <= m; ++i) {
        if(e[i].pass) continue;
        int u = e[i].u, v = e[i].v;
        if(!((dep[u] + dep[v]) & 1)) {
            modify(u, v, 1);
            cnt++;
            if(cnt == 1) sp = i;
        }
        else modify(u, v, -1);
    }
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= n; ++i) {
        if(!vis[i]) df5(i, 0);
    }
    if(cnt == 0) {
        for (int i = 1; i <= m; ++i) ans[i] = 1;
    }
    else {
        for (int i = 1; i <= m; ++i) {
            if(e[i].pass && w[i] == cnt) {
                ans[i] = 1;
            }
        }
        if(cnt == 1) ans[sp] = 1;
    }
    int k = 0;
    for (int i = 1; i <= m; ++i) k += ans[i];
    printf("%d\n", k);
    for (int i = 1; i <= m; ++i) {
        if(ans[i]) printf("%d ", i);
    }
    return ;
}

int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        scanf("%d %d", &e[i].u, &e[i].v);
        e[i].pass = 0;
    }
    Spanning();
    for (int i = 1; i <= n; ++i) {
        if(!vis[i]) dfs(i);
    }
    Extend();
    return 0;
}
2023/6/27 21:45
加载中...