zoukankan      html  css  js  c++  java
  • POJ3694 Network

    Description

    给定$N$个点和 $M$条边的无向联通图, 有$Q$ 次操作, 连接两个点的边, 问每次操作后的图中有几个桥

    Solution

    首先Tarjan找出边双联通分量, 每个双联通分量缩成一个点, 就构成了一棵树, 每一条树边都是桥。

    执行连$u, v$ 边时, 用并查集跳到没有桥的深度最浅并且深度比$lca$深的点, 将它与父节点的并查集合并, 再接着跳。

    每跳一次, 桥的数量就减少$1$。

    另外感谢Iowa 神犇提醒我$cut$数组要开$M << 1$, 不是 $N << 1$, 拯救了$RE$崩溃的我呜呜

    Code

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define rd read()
      5 using namespace std;
      6 
      7 const int N = 1e5 + 1e4;
      8 const int M = 2e5 + 1e4;
      9 
     10 int n, m, dfn[N], low[N], cnt; 
     11 int head[N], tot;
     12 int Head[N], Tot;
     13 int col[N], col_num, father[N], ans;
     14 int top[N], son[N], size[N], f[N], dep[N];
     15 int cut[M << 1];
     16 
     17 struct edge {
     18     int nxt, to;
     19 }E[M << 1], e[M << 1];
     20 
     21 int read() {
     22     int X = 0, p = 1; char c = getchar();
     23     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
     24     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
     25     return X * p;
     26 }
     27 
     28 void add(int u, int v) {
     29     e[++tot].to = v;
     30     e[tot].nxt = head[u];
     31     head[u] = tot;
     32 }
     33 
     34 void Add(int u, int v) {
     35     E[++Tot].to = v;
     36     E[Tot].nxt = Head[u];
     37     Head[u] = Tot;
     38 }
     39 
     40 void dfs1(int u) {
     41     size[u] = 1;
     42     for(int i = Head[u]; i; i = E[i].nxt) {
     43         int nt = E[i].to;
     44         if(nt == f[u]) continue;
     45         f[nt] = u;
     46         dep[nt] = dep[u] + 1;
     47         dfs1(nt);
     48         size[u] += size[nt];
     49         if(size[nt] > size[son[u]]) son[u] = nt;
     50     }
     51 }
     52 
     53 void dfs2(int u) {
     54     if(!son[u]) return;
     55     top[son[u]] = top[u];
     56     dfs2(son[u]);
     57     for(int i = Head[u]; i; i = E[i].nxt) {
     58         int nt = E[i].to;
     59         if(nt == f[u] || nt == son[u]) continue;
     60         top[nt] = nt;
     61         dfs2(nt);
     62     }
     63 }
     64 
     65 int LCA(int x, int y) {
     66     for(; top[x] != top[y];) {
     67         if(dep[top[x]] < dep[top[y]]) swap(x, y);
     68         x = f[top[x]];
     69     }
     70     if(dep[x] < dep[y]) swap(x, y);
     71     return y;
     72 }
     73 
     74 int get(int x) {
     75     return father[x] == x? x : father[x] = get(father[x]);
     76 }
     77 
     78 void merg(int x, int y) {
     79     x = get(x); y = get(y);
     80     father[x] = y;
     81 }
     82 
     83 int ch(int x) {
     84     return ((x + 1) ^ 1) - 1;
     85 }
     86 
     87 void tarjan(int u, int pre) {
     88     dfn[u] = low[u] = ++cnt;
     89     for(int i = head[u]; i; i = e[i].nxt) {
     90         if(i == ch(pre)) continue; 
     91         int nt = e[i].to;
     92                 if(!dfn[nt]) {
     93                     tarjan(nt, i);
     94                     low[u] = min(low[u], low[nt]);
     95                     if(low[nt] > dfn[u]) {
     96                         cut[ch(i)] = cut[i] = 1;
     97                         ans++;
     98                     }
     99                 }
    100                 else low[u] = min(low[u], dfn[nt]);
    101     }
    102 }
    103 
    104 void dfs(int u) {
    105     col[u] = col_num;
    106     for(int i = head[u]; i; i = e[i].nxt) {
    107         int nt = e[i].to;
    108         if(col[nt] || cut[i]) continue;
    109         dfs(nt);
    110         //blo[col_num].push_back(nt);
    111     }
    112 }
    113 
    114 void work() {
    115     ans = Tot = tot = cnt = col_num = 0;
    116     memset(Head, 0, sizeof(Head));
    117     memset(head, 0, sizeof(head));
    118     memset(cut, 0, sizeof(cut));
    119     memset(dfn, 0, sizeof(dfn));
    120     memset(col, 0, sizeof(col));
    121     memset(son, 0, sizeof(son));
    122     memset(size, 0, sizeof(size));
    123     for(int i = 1; i <= m; ++i) {
    124         int u = rd, v = rd;
    125         add(u, v); add(v, u);
    126     }
    127     for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i, 0);
    128     for(int i = 1; i <= n; ++i) if(!col[i]) {
    129         ++col_num; dfs(i);
    130     }
    131     for(int i = 1; i <= tot; ++i) {
    132         int x = e[i].to, y = e[ch(i)].to;
    133         if(col[x] == col[y]) continue;
    134         Add(col[x], col[y]);
    135     }
    136     for(int i = 1; i <= col_num; ++i) father[i] = i;
    137     dfs1(1);
    138     top[1] = 1; dfs2(1);
    139     int T = rd;
    140     for(; T; T--) {
    141         int u = col[rd], v = col[rd], lca = LCA(u, v);
    142         u = get(u); v = get(v);
    143         while(dep[u] > dep[lca]) {
    144             merg(u, f[u]);
    145             u = get(u);
    146             ans --;
    147         }
    148         while(dep[v] > dep[lca]) {
    149             merg(v, f[v]);
    150             v = get(v);
    151             ans --;
    152         }
    153         printf("%d
    ", ans);
    154     }
    155 }
    156 
    157 int main()
    158 {
    159     for(int i = 1; ; ++i) {
    160         n = rd; m = rd;
    161         if(!n && !m) return 0;
    162         printf("Case %d:
    ", i);
    163         work();
    164         putchar('
    ');
    165     }
    166 }
    View Code
  • 相关阅读:
    布局类组件介绍
    容器类组件介绍
    应用升级介绍
    Http组件的介绍
    Webview组件和HTML的介绍
    数据绑定介绍
    业界最具影响力MySQL精品文章荟萃(300篇)
    业界最有价值的 ASP.NET 博文汇总
    一个引号导致1个小时网站打不开
    这个世界从来没有任何一件工作叫“钱多、事少、离家近”
  • 原文地址:https://www.cnblogs.com/cychester/p/9626945.html
Copyright © 2011-2022 走看看