zoukankan      html  css  js  c++  java
  • Poj 3694 Network (连通图缩点+LCA+并查集)

    题目链接:

      Poj 3694 Network

    题目描述:

      给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥?

    解题思路:

      先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条边两个端点根节点的LCA,统计其中的桥,然后把这个环中的节点加到一个集合中,根节点标记为LCA。

    题目不难,坑在了数组初始化和大小

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 const int maxn = 100005;
      8 struct node
      9 {
     10     int to, next;
     11 } edge[4*maxn], Edge[2*maxn];
     12 int head[maxn], low[maxn], dfn[maxn], id[maxn], Head[maxn], Father[maxn];
     13 int pre[maxn], deep[maxn], stack[maxn], tot, ntime, top, cnt, Tot;
     14 
     15 void init ()
     16 {
     17     Tot = tot = ntime = top = cnt = 0;
     18     memset (id, 0, sizeof(id));
     19     memset (low, 0, sizeof(low));
     20     memset (dfn, 0, sizeof(dfn));
     21     memset (pre, 0, sizeof(pre));
     22     memset (head, -1, sizeof(head));
     23     memset (deep, 0, sizeof(deep));
     24     memset (Head, -1, sizeof(Head));
     25 }
     26 void Add (int from, int to)
     27 {
     28     Edge[Tot].to = to;
     29     Edge[Tot].next = Head[from];
     30     Head[from] = Tot++;
     31 }
     32 void add (int from, int to)
     33 {
     34     edge[tot].to = to;
     35     edge[tot].next = head[from];
     36     head[from] = tot++;
     37 }
     38 int find (int x)
     39 {
     40     if (x != Father[x])
     41         Father[x] = find(Father[x]);
     42     return Father[x];
     43 }
     44 void dfs (int u, int father, int d)
     45 {
     46     pre[u] = father;
     47     deep[u] = d;
     48     for (int i=Head[u]; i!=-1; i=Edge[i].next)
     49     {
     50         int v = Edge[i].to;
     51         if (father != v)
     52             dfs (v, u, d+1);
     53     }
     54 }
     55 int LCA (int a, int b)
     56 {
     57     while (a != b)
     58     {
     59         if (deep[a] > deep[b])
     60             a = pre[a];
     61         else if (deep[a] < deep[b])
     62             b = pre[b];
     63         else
     64         {
     65             a = pre[a];
     66             b = pre[b];
     67         }
     68         a = find (a);
     69         b = find (b);
     70     }
     71     return a;
     72 }
     73 void Tarjan (int u, int father)
     74 {
     75     int k = 0;
     76     low[u] = dfn[u] = ++ ntime;
     77     stack[top ++] = u;
     78     for (int i=head[u]; i!=-1; i=edge[i].next)
     79     {
     80         int v = edge[i].to;
     81         if (father == v && !k)
     82         {
     83             k ++;
     84             continue;
     85         }
     86         if (!dfn[v])
     87         {
     88             Tarjan (v, u);
     89             low[u] = min (low[u], low[v]);
     90         }
     91         else
     92             low[u] = min (low[u], dfn[v]);
     93     }
     94     if (low[u] == dfn[u])
     95     {
     96         cnt ++;
     97         while (1)
     98         {
     99             int v = stack[--top];
    100             id[v] = cnt;
    101             if (v == u)
    102                 break;
    103         }
    104     }
    105 }
    106 void solve (int n)
    107 {
    108     Tarjan (1, 0);
    109     for (int i=1; i<=n; i++)
    110         for (int j=head[i]; j!=-1; j=edge[j].next)
    111         {
    112             int u = id[i];
    113             int v = id[edge[j].to];
    114             if (u != v)
    115                 Add (u, v);
    116         }
    117     dfs (1, 0, 0);
    118     
    119     for (int i=0; i<=cnt; i++)
    120         Father[i] = i;
    121     int q;
    122     cnt --;
    123     scanf ("%d", &q);
    124     while (q --)
    125     {
    126         int u, v;
    127         scanf ("%d %d", &u, &v);
    128         u = find(id[u]);
    129         v = find(id[v]);
    130         int lca = LCA(u, v);
    131         while (u != lca)
    132         {
    133             cnt --;
    134             Father[u] = lca;
    135             u = find (pre[u]);
    136         }
    137         while (v !=lca)
    138         {
    139             cnt --;
    140             Father[v] = lca;
    141             v = find (pre[v]);
    142         }
    143         printf ("%d
    ", cnt);
    144     }
    145 }
    146 int main ()
    147 {
    148     int n, m, l = 0;
    149     while (scanf ("%d %d",&n, &m), n + m)
    150     {
    151         init ();
    152         while (m --)
    153         {
    154             int u, v;
    155             scanf ("%d %d", &u, &v);
    156             add (u, v);
    157             add (v, u);
    158         }
    159         printf ("Case %d:
    ", ++l);
    160         solve (n);
    161         printf ("
    ");
    162     }
    163     return 0;
    164 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    laravel 需要用到的命令行
    人生信条
    25岁之前,请记得,爱情通常是假的,或者不是你所想象的那样纯洁和永远。如果你过了25岁,那么你应该懂得这个道理。30岁之前请爱惜自己的身体,前30年你找病,后30年病找你。如果你过了30岁,你自然也会懂得这个道理。
    剑指offer——和为S的两个数字
    剑指offer——和为S的连续正数序列
    剑指offer——将复杂问题分解使其简单化
    剑指offer——二叉树中和为某一值的路径
    递归递归!!!
    芒种喜雨,端午前日
    由KTT展开的一系列知识点
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4674248.html
Copyright © 2011-2022 走看看