hdu 2460 Network (双连通分支+暴力LCA)

题意:在一张图中给出q个加边操作,问你每次操作之后图中割边的个数。点数1e5询问1000

思路:这道题的做法是先对图进行缩点,然后变成一颗树,每次添加新边若是边的两个端点属于不同的分支则一定会形成一个环,这时暴力lca标记所有换上的边有割边变为不是割边。每次统计就可以了。理论上说,每次给V字形的图复杂度会是1e8还有多组数据可能会超时,但这道题能通过。另外这道题会爆栈,注意c++扩栈。

代码如下:

  1 /**************************************************
  2  * Author     : xiaohao Z
  3  * Blog     : http://www.cnblogs.com/shu-xiaohao/
  4  * Last modified : 2014-09-01 15:25
  5  * Filename     : hdu_2460.cpp
  6  * Description     :
  7  * ************************************************/
  8 #pragma comment(linker, "/STACK:1024000000,1024000000")
  9 #include <iostream>
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <string>
 14 #include <cmath>
 15 #include <algorithm>
 16 #include <queue>
 17 #include <stack>
 18 #include <vector>
 19 #include <set>
 20 #include <map>
 21 #define MP(a, b) make_pair(a, b)
 22 #define PB(a) push_back(a)
 23
 24 using namespace std;
 25 typedef long long ll;
 26 typedef pair<int, int> pii;
 27 typedef pair<unsigned int,unsigned int> puu;
 28 typedef pair<int, double> pid;
 29 typedef pair<ll, int> pli;
 30 typedef pair<int, ll> pil;
 31
 32 const int INF = 0x3f3f3f3f;
 33 const double eps = 1E-6;
 34 const int LEN = 100010;
 35 vector<int> Map[LEN], tMap[LEN];
 36 stack<int> s;
 37 int n, m, dclock, low[LEN], dfn[LEN], block, blong[LEN];
 38 int dep[LEN], parent[LEN], is[LEN];
 39
 40 void init()
 41 {
 42     memset(dfn, -1, sizeof dfn);
 43     memset(is, 0, sizeof is);
 44     memset(parent, 0, sizeof parent);
 45     dclock = is[1] = 1; block = 0;
 46     while(!s.empty())s.pop();
 47     for(int i=0; i<LEN; i++) Map[i].clear();
 48 }
 49
 50 void dfs(int u, int fa){
 51     int v, flag = 0;
 52     dfn[u] = low[u] = dclock++;
 53     s.push(u);
 54     for(int i=0; i<Map[u].size(); i++){
 55         v = Map[u][i];
 56         if(v==fa && !flag){flag = 1;continue;}
 57         if(dfn[v]<0){
 58             dfs(v, u);
 59             low[u] = min(low[u], low[v]);
 60         }else if(low[u]>low[v]) low[u] = min(low[u], dfn[v]);
 61     }
 62     if(low[u] == dfn[u]){
 63         block ++;
 64         do{
 65             v = s.top(); s.pop();
 66             blong[v] = block;
 67         }while(v!=u);
 68     }
 69 }
 70
 71 void DFS(int v, int fa, int d){
 72     dep[v] = d;
 73     parent[v] = fa;
 74     for(int i=0; i<tMap[v].size(); i++){
 75         int x = tMap[v][i];
 76         if(x != fa)    DFS(x, v, d+1);
 77     }
 78 }
 79
 80 void build(){
 81     int a, b;
 82     map<pii, int> mp; mp.clear();
 83     for(int i=0; i<LEN; i++) tMap[i].clear();
 84     for(int i=0; i<n; i++)
 85         for(int j=0; j<Map[i].size(); j++){
 86             int x = Map[i][j];
 87             if(blong[i] == blong[x]) continue;
 88             a = blong[i], b = blong[x];
 89             if(mp.count(MP(a, b))) continue;
 90             mp[MP(a, b)] = mp[MP(b, a)] = 1;
 91             tMap[a].PB(b); tMap[b].PB(a);
 92         }
 93     DFS(1, 0, 0);
 94 }
 95
 96 void _(int val) {cout << "\"" << val << endl;}
 97
 98
 99 void lca(int a, int b){
100     if(dep[a] < dep[b]) swap(a, b);
101     int tmp = dep[a] - dep[b];
102     for(int i=0; i<tmp; i++) {
103         if(!is[a]) {is[a] = 1;block --;}
104         a = parent[a];
105     }
106     while(a != b) {
107         if(!is[a]) {is[a] = 1; block --;}
108         if(!is[b]) {is[b] = 1; block --;}
109         a = parent[a], b = parent[b];
110     }
111 }
112
113 int main()
114 {
115 //    freopen("in.txt", "r", stdin);
116
117     int a, b, q, kase = 1;
118     while(scanf("%d%d", &n, &m) != EOF){
119         if(!n && !m) break;
120         init();
121         for(int i=0; i<m; i++){
122             scanf("%d%d", &a, &b);
123             a--, b--;
124             Map[a].PB(b); Map[b].PB(a);
125         }
126         dfs(0, -1);
127         build();
128         scanf("%d", &q);
129         printf("Case %d:\n", kase ++);
130         for(int i=0; i<q; i++){
131             scanf("%d%d", &a, &b);
132             a--; b--;
133             if(blong[a] != blong[b]) lca(blong[a], blong[b]);
134             printf("%d\n", block - 1);
135         }
136         puts("");
137     }
138     return 0;
139 }

时间: 2024-08-07 00:16:54

hdu 2460 Network (双连通分支+暴力LCA)的相关文章

HDU 2460 Network(桥+LCA)

http://acm.hdu.edu.cn/showproblem.php?pid=2460 题意:给出图,求每次增加一条边后图中桥的数量. 思路: 先用tarjan算法找出图中所有的桥,如果lowv>pre[u],那么u—v就是桥,此时可以标记一下v. 之后就是利用LCA,找到两个节点的公共祖先,在这条路径上的桥就不再是桥了.(此时就相当于这些桥组成的树,可以在脑海中缩点) 1 #include<iostream> 2 #include<algorithm> 3 #incl

HDU - 2460 Network(桥+LCA)

题目大意:给出一张图,现在要往这张图上加边,问加完边后,这张图还有多少条桥 解题思路:求出连通分量,压缩成点,用桥连接,形成了棵树 每次添加边时,就找一下是否在同一个强连通分量内,如果在同一个强连通分量内,那么桥的数量不变 反之,求出两个点的LCA,并且把LCA到这两个点的桥全部去掉(因为加边后,形成了环,构成了一个新的强连通分量了) #include <cstdio> #include <cstring> using namespace std; #pragma comment(

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

HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链剖分+线段树处理 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #pragma comment(linke

HDU 2460 Network 傻逼Tarjan

Network Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1014    Accepted Submission(s): 206 Problem Description A network administrator manages a large network. The network consists of N comput

HDU 4499 Cannon (暴力搜索)

题意:在n*m的方格里有t个棋子,问最多能放多少个炮且每个炮不能互相攻击(炮吃炮) 炮吃炮:在同一行或同一列且中间有一颗棋子. #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #define M 50 #define LL long long using

HDU 4902 线段树||暴力

给定一个序列,两种操作 1:把一段变成x. 2:把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 线段树解法:用lazy标记下即可,优化方法还是很巧妙的, Accepted 4902 515MS 3308K 1941 B C++ #include "stdio.h" #include "string.h" struct node { int l,r,x;// 在叶子节点代表值,树节点代表成端更新的lazy操作. }data[400010]

HDU 4008 Parent and son LCA+树形dp

题意: 给定case数 给定n个点的树,m个询问 下面n-1行给出树边 m个询问 x y 问:以x为根,y子树下 y的最小点标的儿子节点 和子孙节点 思路: 用son[u][0] 表示u的最小儿子 son[u][2] 表示u的次小儿子 son[u][1] 表示u的最小子孙 若lca(x,y)  !=y  则就是上述的答案 若lca(x,y) == y 1.y != 1 那么最小儿子就是除了x外的节点,且此时father[y] 也是y的儿子节点, 而最小的子孙节点就是1 2.y==1 那么特殊处理

HDU 4831 Scenic Popularity 暴力模拟

Scenic Popularity Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 340    Accepted Submission(s): 110 Problem Description 临近节日,度度熊们最近计划到室外游玩公园,公园内部包括了很多的旅游景点区和休息区,由于旅游景点很热门,导致景点区和休息区都聚集了很多人.所以度度熊

HDU 4961 Boring Sum 暴力

题意:对于所有的A[I],同时找到左边和右边离它最近且是它的倍数的数相乘最后加起来求和. 解题思路:n*sqrt(n)的算法,开始以为过不了,wa了两发因为lld I64d对拍一个小时发现一个小时前交的代码没错只是没变I64d,..具体思路是枚举每个a[i]的因子,找离它最近的那个更新,如果已经没更新就不用更新了.用两个辅助数组记录最近的就行. 解题代码: 1 // File Name: 1002.cpp 2 // Author: darkdream 3 // Created Time: 201