AT3968 [AGC025E] Walking on a Tree

https://www.luogu.com.cn/problem/AT3968

lj翻译
c [ i ] c[i] c[i]为第 i i i条边被覆盖的次数,对 2 2 2取min

上界一定可以达到,证明可以从叶子结点开始考虑,归纳证明

然后考虑如何构造,当然可以想证明一样构造,不过很麻烦

把路径建一个图,容易发现,如果是对于每个路径的联通块,并且存在欧拉回路,那么欧拉回路就是一个构造方案,即每个节点的度数必须是偶数,如果不是只需和父亲连一条边,用dfs处理即可

正确性不难证明

code:


#include<bits/stdc++.h>
#define N 50050
using namespace std;
struct edge {
    int v, nxt, c;
} e[N << 1];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v, int c) {
    e[eid].v = v;
    e[eid].c = c;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}
int tot, L[N], R[N], fa[N][15], in[N], dep[N], vis[N << 2], n, m, U[N], V[N];
vector<int> g[N];
void dfs(int u) {
    L[u] = ++ tot;
    for(int v : g[u]) {
        if(v == fa[u][0]) continue;
        fa[v][0] = u; dep[v] = dep[u] + 1;
        dfs(v);
        if(in[v] & 1) {
            in[u] ++, in[v] ++;
            insert(u, v, 0), insert(v, u, 0);
        }
    }
    R[u] = tot;
}
int LCA(int x, int y) {
    if(dep[x] < dep[y]) swap(x, y);
    for(int i = 12; i >= 0; i --) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
    if(x == y) return x;
    for(int i = 12; i >= 0; i --) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}
void dfss(int u) {
    for(int &i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v, id = e[i].c;
        if(!vis[i]) {
            vis[i] = vis[i ^ 1] = 1;
            if(id < 0) id = - id, swap(U[id], V[id]);
            dfss(v);
        }
    }
}
#define lowbit(x) (x & -x)
int t[N];
void update(int x, int y) {
    for(; x <= n; x += lowbit(x)) t[x] += y;
}
int query(int x) {
    int ret = 0;
    for(; x; x -= lowbit(x)) ret += t[x];
    return ret;
}
int main() {
    init();
    scanf("%d%d", &n, &m);
    for(int i = 1; i < n; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        g[u].push_back(v), g[v].push_back(u);
    }

    for(int i = 1; i <= m; i ++) {
        int u, v;
        scanf("%d%d", &u, &v); U[i] = u, V[i] = v;
        in[u] ++, in[v] ++;
        insert(u, v, i), insert(v, u, - i);
    }   
    dep[1] = 1;
    dfs(1);
    for(int j = 1; j <= 12; j ++)
        for(int i = 1; i <= n; i ++) fa[i][j] = fa[fa[i][j - 1]][j - 1];
    
   // for(int i = 1; i <= n; i ++) printf("%d ", fa[i][0]); printf("\n");
    for(int i = 1; i <= m; i ++) {
        int u = U[i], v = V[i];
      //  printf("%d %d %d\n", u, v, LCA(u, v));
        update(L[u], 1), update(L[v], 1), update(L[LCA(u, v)], - 2);
    }
    
    for(int i = 1; i <= n; i ++) dfss(i);
    int ans = 0;
    for(int i = 2; i <= n; i ++) {
        int o = query(R[i]) - query(L[i] - 1);
        ans += min(o, 2);
    }
    printf("%d\n", ans);
    for(int i = 1; i <= m; i ++) printf("%d %d\n", U[i], V[i]);
    return 0;
}
posted @ 2021-11-14 21:16  lahlah  阅读(41)  评论(0编辑  收藏  举报