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\n", 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:\n", ++l);
160         solve (n);
161         printf ("\n");
162     }
163     return 0;
164 }
时间: 2024-12-28 08:43:05

Poj 3694 Network (连通图缩点+LCA+并查集)的相关文章

【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集

[题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1<=wi<=10^9. [算法]最小生成树+倍增LCA+并查集 [题解]首先求出图的一个最小生成树,则所有边分成树边和非树边. 对于非树边(u,v),假设u和v在最小生成树上的路径的最大边权Max,那么一定满足w(u,v)<=Max /////////////////////////////////////// 原文地址:https://ww

【转】POJ 2492 A Bug&#39;s Life:基础并查集进阶

思路参考这里(较详细) 一开始总是WA调了一晚上原来···Init初始化写在scanf上面了···哎╮(╯▽╰)╭anyway!对并查集的理解更深了一步! #include<cstdio> #include<cstring> using namespace std; #define Size 2000 struct node { int Pre; int Relation;// 与父节点的关系 0同性 1异性 }Bug[Size+1]; int N, M; bool found;

HDU 1829 &amp;&amp; POJ 2492 A Bug&#39;s Life(种类并查集)

题目地址:HDU 1829     POJ 2492 这个题可以用两种方法做,第一眼看完题是觉得用dfs染色判断二分图.然后又写的刚学的种类并查集.原来并查集可以这样用,真是神奇.. dfs染色代码: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #incl

Poj 1182种类(带权)并查集

题目链接 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44316 Accepted: 12934 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是

POJ 1611 The Suspects(特别无语的并查集)

很简单的一道题目,开始用的是并查集的分离集合森林做,不知道怎么的特别不稳定,太奇怪了,WA无数次,无奈之下改成一维数组了..sad AC #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <math.h> #define PI acos(-1,0) using namespa

POJ 2492 A Bug&#39;s Life (并查集)

Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, individual bugs and their in

poj 2492 A Bug&#39;s Life 【并查集拓展】

A Bug's Life Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 29030   Accepted: 9455 Description Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders

poj 1182 食物链 (带关系的并查集)

  食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44835 Accepted: 13069 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类.

poj 1733 Parity game【哈希+并查集】

这道题题意我不想说了,但是有一个条件必须的说,就是1-2其实是0-2这条边,3-4是2-4这条边,但是困惑了好久,其他就是哈希给他一个地址 ,然后把注解看下方 #include <stdio.h> #include <string.h> #define maxx 10001 int par[maxx]; int rank[maxx]; void init() { for(int i=0;i<=maxx;i++) { rank[i]=0; par[i]=i; } } int f