HDU 2460 Network(双连通+树链剖分+线段树)

来源:互联网 发布:软件许可使用合同 编辑:程序博客网 时间:2024/06/06 05:49

HDU 2460 Network

题目链接

题意:给定一个无向图,问每次加入一条边,问个图中还剩多少桥

思路:先双连通缩点,然后形成一棵树,每次加入一条边,相当于询问这两点路径上有多少条边,这个用树链剖分+线段树处理

代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000");const int N = 100005;const int M = 200005;int n, m;struct Edge {int u, v, id;bool iscut;Edge() {}Edge(int u, int v, int id) {this->u = u; this->v = v; this->id = id; this->iscut = false;}} edge[M * 2], cut[M];int en, cn, first[N], next[M * 2];void init() {en = 0;memset(first, -1, sizeof(first));}void add_edge(int u, int v, int id) {edge[en] = Edge(u, v, id);next[en] = first[u];first[u] = en++;}int pre[N], dfn[N], dfs_clock;void dfs_cut(int u, int fa) {pre[u] = dfn[u] = ++dfs_clock;for (int i = first[u]; i + 1; i = next[i]) {if (edge[i].id == fa) continue;int v = edge[i].v;if (!pre[v]) {dfs_cut(v, edge[i].id);dfn[u] = min(dfn[u], dfn[v]);if (dfn[v] > pre[u]) {cut[cn++] = edge[i];edge[i].iscut = edge[i^1].iscut = true;}} else dfn[u] = min(dfn[u], pre[v]);}}void find_cut() {cn = dfs_clock = 0;memset(pre, 0, sizeof(pre));for (int i = 1; i <= n; i++)if (!pre[i]) dfs_cut(i, -1);}vector<int> g[N];int bccno[N], bccn;void dfs_bcc(int u) {bccno[u] = bccn;for (int i = first[u]; i + 1; i = next[i]) {if (edge[i].iscut) continue;int v = edge[i].v;if (bccno[v]) continue;dfs_bcc(v);}}void find_bcc() {bccn = 0;memset(bccno, 0, sizeof(bccno));for (int i = 1; i <= n; i++)if (!bccno[i]) {bccn++;dfs_bcc(i);}for (int i = 1; i <= bccn; i++) g[i].clear();for (int i = 0; i < cn; i++) {int u = bccno[cut[i].u], v = bccno[cut[i].v];g[u].push_back(v);g[v].push_back(u);}}int dep[N], fa[N], son[N], sz[N], top[N], id[N], idx;void dfs1(int u, int f, int d) {dep[u] = d; sz[u] = 1; fa[u] = f; son[u] = 0;for (int i = 0; i < g[u].size(); i++) {int v = g[u][i];if (v == f) continue;dfs1(v, u, d + 1);sz[u] += sz[v];if (sz[son[u]] < sz[v])son[u] = v;}}void dfs2(int u, int tp) {id[u] = ++idx; top[u] = tp;if (son[u]) dfs2(son[u], tp);for (int i = 0; i < g[u].size(); i++) {int v = g[u][i];if (v == fa[u] || v == son[u]) continue;dfs2(v, v);}}#define lson(x) ((x<<1)+1)#define rson(x) ((x<<1)+2)struct Node {int l, r, sum, flag;void gao() {sum = 0;flag = 1;}} node[N * 4];void build(int l, int r, int x = 0) {node[x].l = l; node[x].r = r; node[x].flag = 0;node[x].sum = r - l + 1;if (l == r) return;int mid = (l + r) / 2;build(l, mid, lson(x));build(mid + 1, r, rson(x));}void pushup(int x) {node[x].sum = node[lson(x)].sum + node[rson(x)].sum;}void pushdown(int x) {if (node[x].flag) {node[lson(x)].gao();node[rson(x)].gao();node[x].flag = 0;}}int query(int l, int r, int x = 0) {if (node[x].l >= l && node[x].r <= r) {int ans = node[x].sum;node[x].gao();return ans;}pushdown(x);int mid = (node[x].l + node[x].r) / 2;int ans = 0;if (l <= mid) ans += query(l, r, lson(x));if (r > mid) ans += query(l, r, rson(x));pushup(x);return ans;}int gao(int u, int v) {int tp1 = top[u], tp2 = top[v];int ans = 0;while (tp1 != tp2) {if (dep[tp1] < dep[tp2]) {swap(tp1, tp2);swap(u, v);}ans += query(id[tp1], id[u]);u = fa[tp1];tp1 = top[u];}if (u == v) return ans;if (dep[u] > dep[v]) swap(u, v);ans += query(id[son[u]], id[v]);return ans;}int main() {int cas = 0;while (~scanf("%d%d", &n, &m) && n || m) {init();int u, v;for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);add_edge(u, v, i);add_edge(v, u, i);}find_cut();find_bcc();idx = 0;dfs1(1, 0, 1);dfs2(1, 1);int q;scanf("%d", &q);printf("Case %d:\n", ++cas);build(1, n);while (q--) {scanf("%d%d", &u, &v);u = bccno[u]; v = bccno[v];cn -= gao(u, v);printf("%d\n", cn);}printf("\n");}return 0;}


1 0
原创粉丝点击