5pts 求 hack
查看原帖
5pts 求 hack
655192
Tibrella楼主2023/3/26 21:58

思路:求边双之后因为每个点只会包含在一个边双内,所以给点编号为所在边双的序号,再通过这个进行缩点。

缩点过程中记录新边所对应的原边 e->ori 和无向图中对应的反向边 e->opp,并开 bool 型记录其是否是反向边,然后输入要求的 x,y,记录树上点差分数组 p[x]++,p[y]--,然后进行 dfs 统计答案

dfs 中,对于当前点 xx 的子节点 yy 及连边 e(x,y)e(x,y)(向下连接的边) 来说,如果 p[y] > 0 则:

  • 如果 ee 是反向边,则将其反向边(即新图中的正向边)对应的原图边的方向设为 L
    否则相反,方向设为 R

p[y] < 0 则与上述情况相反

其余未标记边方向为 B

最后遍历所有原边且为正向的边输出答案

请问思路有问题吗

#pragma GCC target("avx2")

#include <algorithm>
#include <bitset>
#include <cstring>
#include <iostream>

using std::bitset;
using std::cin;
using std::cout;
using std::max;
using std::min;

const char endl = '\n';
const int N = 100500;

struct edge {
    edge *nex, *opp;
    int fr, to;
    bool cut, rev;
    char data;
    edge* ori;
} graph[N], aft[N];
edge *fir[N], *tot = graph;

void add(int& a, int& b) {
    tot->data = 'B';
    tot->fr = a;
    tot->to = b;
    tot->opp = tot + 1;
    tot->nex = fir[a];
    fir[a] = tot;
    ++tot;

    tot->fr = b;
    tot->to = a;
    tot->rev = true;
    tot->opp = tot - 1;
    tot->nex = fir[b];
    fir[b] = tot;
    ++tot;
}

void add(int& a, int& b, edge* e) {
    tot->data = 'B';
    tot->ori = e;
    tot->fr = a;
    tot->to = b;
    tot->opp = tot + 1;
    tot->nex = fir[a];
    fir[a] = tot;
    ++tot;

    tot->ori = e->opp;
    tot->fr = b;
    tot->to = a;
    tot->opp = tot - 1;
    tot->rev = true;
    tot->nex = fir[b];
    fir[b] = tot;
    ++tot;
}

int dfn[N], low[N], tim;
int id[N];
int ecc_cnt;

void tarjan(int nod, edge* edg) {
    dfn[nod] = low[nod] = ++tim;

    for (edge* e = fir[nod]; e; e = e->nex) {
        if (!dfn[e->to]) {
            tarjan(e->to, e);
            low[nod] = min(low[nod], low[e->to]);
            if (low[nod] < low[e->to]) {
                e->cut = e->opp->cut = true;
            }
        } else if (!edg || e != edg->opp) {
            low[nod] = min(low[nod], dfn[e->to]);
        }
    }
}

void add_up(int nod) {
    id[nod] = ecc_cnt;
    for (edge* e = fir[nod]; e; e = e->nex) {
        if (id[e->to] || e->cut) continue;
        add_up(e->to);
    }
}

int p[N];

void dfs(int nod, int fa) {
    int res = 0;
    for (edge* e = fir[nod]; e; e = e->nex) {
        if (e->to == fa) continue;
        dfs(e->to, nod);
        if (p[e->to] > 0) {
            if (e->rev) {
                e->ori->opp->data = 'L';
            } else {
                e->ori->data = 'R';
            }
        } else if (p[e->to] < 0) {
            if (e->rev) {
                e->ori->opp->data = 'R';
            } else {
                e->ori->data = 'L';
            }
        }
        res += p[e->to];
    }
    p[nod] += res;
}

void solve() {
    std::ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    tot = aft;
    memset(fir, 0, sizeof fir);
    for (edge* e = graph; e->to; ++e) {
        if (!e->rev && id[e->fr] != id[e->to]) add(id[e->fr], id[e->to], e);
    }
    dfs(1, 0);
    for (edge* e = graph; e->to; ++e)
        if (!e->rev) cout << e->data;
}

int n, m, t;
int t1, t2;

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    cin >> n >> m;
    for (int i = 1; i <= m; ++i) {
        cin >> t1 >> t2;
        add(t1, t2);
    }

    for (int i = 1; i <= n; ++i)
        if (!dfn[i]) tarjan(i, nullptr);

    for (int i = 1; i <= n; ++i) {
        if (!id[i]) {
            ++ecc_cnt;
            add_up(i);
        }
    }

    // for (int i = 1; i <= n; ++ i) {
    //     cout << i << ' ' << id[i] << '\n';
    // }

    cin >> t;
    for (int i = 1; i <= t; ++i) {
        cin >> t1 >> t2;
        ++p[id[t1]];
        --p[id[t2]];
    }
    solve();

    return 0;
}
2023/3/26 21:58
加载中...