poj3694(lca + tarjan求桥模板)

题目链接: http://poj.org/problem?id=3694

题意: 给出一个 n 个节点 m 条边的图, 然后有 q 组形如 x, y 的询问, 在前面的基础上连接边 x, y, 输出当前图中有多少桥 .

思路: http://www.cnblogs.com/scau20110726/archive/2013/05/29/3106073.html

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5
 6 const int MAXN = 1e5 + 10;
 7
 8 struct node{
 9     int v, next, use;
10 }edge[MAXN << 2];
11
12 bool bridge[MAXN];
13 int low[MAXN], dfn[MAXN], vis[MAXN];
14 int head[MAXN], pre[MAXN], ip, sol, count;
15
16 void init(void){
17     memset(head, -1, sizeof(head));
18     memset(vis, false, sizeof(vis));
19     memset(bridge, false, sizeof(bridge));
20     count = sol = ip = 0;
21 }
22
23 void addedge(int u, int v){
24     edge[ip].v = v;
25     edge[ip].use = 0;
26     edge[ip].next = head[u];
27     head[u] = ip++;
28 }
29
30 void tarjan(int u){
31     vis[u] = 1;
32     dfn[u] = low[u] = count++;
33     for(int i = head[u]; i != -1; i = edge[i].next){
34         if(!edge[i].use){
35             edge[i].use = edge[i ^ 1].use = 1;
36             int v = edge[i].v;
37             if(!vis[v]){
38                 pre[v] = u;
39                 tarjan(v);
40                 low[u] = min(low[u], low[v]);
41                 if(dfn[u] < low[v]){
42                     sol++;
43                     bridge[v] = true;
44                 }
45             }else if(vis[v] == 1){
46                 low[u] = min(low[u], dfn[v]);
47             }
48         }
49     }
50     vis[u] = 2;
51 }
52
53 void LCA(int u, int v){
54     if(dfn[u] > dfn[v]) swap(u, v);
55     while(dfn[v] > dfn[u]){//判断一下u,v是否在同一条树枝上
56         if(bridge[v]) sol--;
57         bridge[v] = false;
58         v = pre[v];
59     }
60     while(u != v){//找lca
61         if(bridge[u]) sol--;
62         if(bridge[v]) sol--;
63         bridge[u] = bridge[v] = false;
64         u = pre[u];
65         v = pre[v];
66     }
67 }
68
69 int main(void){
70     int n, m, q, x, y, cas = 1;
71     while(~scanf("%d%d", &n, &m)){
72         if(!n && !m) break;
73         init();
74         for(int i = 0; i < m; i++){
75             scanf("%d%d", &x, &y);
76             addedge(x, y);
77             addedge(y, x);
78         }
79         pre[1] = 1;
80         tarjan(1);
81         printf("Case %d:\n", cas++);
82         scanf("%d", &q);
83         while(q--){
84             scanf("%d%d", &x, &y);
85             LCA(x, y);
86             printf("%d\n", sol);
87         }
88         puts("");
89     }
90     return 0;
91 }

时间: 2024-10-27 12:47:50

poj3694(lca + tarjan求桥模板)的相关文章

【模板】【hdu4738】Caocao&#39;s Bridges——tarjan求桥

题目链接 题目大意: 曹操有N个岛,这些岛用M座桥连接起来,每座桥有士兵把守(也可能没有), 诸葛亮把所有炸弹都带走了,只留下一枚给周瑜(真狠). 周瑜想让这N个岛不连通,但需要派出不小于守桥士兵数的人去炸桥,因为只有一枚炸弹,因此只够炸掉一座桥. 分析: 很明显的求代价最小的桥,当然这道题有几个特殊的地方: 1.图本来就不联通,输出0: 2.无解(不存在桥),输出-1: 3.没人把守,但你还是得派一个人炸桥,输出1: 4.一般情况,输出最小代价. 剩下的就是模板了,不过需要注意的一点是,这道题

HDU 4738 Caocao&#39;s Bridges tarjan求桥

Caocao's Bridges Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good at water battles, so he came up with another idea. He built many islands in the Chan

Tarjan求桥和割点

//Tarjan 求桥和割点 Tarjan(u,fa) { DFN[u]=LoW[u]=++time; Cu=grey; for each e=(u,v) { Tarjan(v,u); if(Cv=white) { low[u]=min(low[u],low[v]); }else { low[u]=min(low[u],DFN[v]); } } }

tarjan求桥、割顶

若low[v]>dfn[u],则(u,v)为割边.但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理.我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父亲到它的边的标号,如果边(u,v)是v的父亲边,就不能用dfn[u]更新low[v].这样如果遍历完v的所有子节点后,发现low[v]=dfn[v],说明u的父亲边(u,v)为割边. void tarjan(int x) { vis[x]=1; dfn[x]=low[x]=++num; for(int i

Codeforces 700 C. Break Up(Tarjan求桥)

题意 给你一个有 \(n\) 个点, \(m\) 条边的无向图,每条有边权 \(w_i\) ,现在要选择至多两条边断开,使得 \(S, T\) 不连通,并且使得边权和尽量小. \(n \le 1000, m \le 30000\) 题解 我们分要选的边数进行考虑. \(0\) 条边:一开始 \(S,T\) 不连通直接判掉即可. \(1\) 条边:我们发现数据较小,可以暴力做.首先这条边必定存在于 \(S,T\) 在 Dfs 树的路径上,一开始先 Dfs 求出路径,然后依次枚举每条边断开,再用 D

POJ 题目3694 Network(tarjan,LCA,求桥)

Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7179   Accepted: 2600 Description A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers

UVA796 - Critical Links(Tarjan求桥)

In a computer network a link L, which interconnects two servers, is considered critical if there are atleast two servers A and B such that all network interconnection paths between A and B pass through L.Removing a critical link generates two disjoin

受欢迎的牛 tarjan求scc模板

第一遍不太熟,第二遍飞快地打出来了 算是tarjan模板了吧,几天了也总算是有一点对tarjan求法过程的理解了. if(!dfn[u])tarjan(u),low[x] = min(low[x],low[u]);//如果没有访问过u,则tarjan一下,如果u走出去搞到的low更小则用这个更新x的low else if(ins[u])low[x] = min(low[x],dfn[u]);//如果u访问过但在栈里,那么u的low说不定已经被更新过了,如果此时令low[x]与low[u]取min

Tarjan求强连通分量、求桥和割点模板

Tarjan 求强连通分量模板.参考博客 #include<stdio.h> #include<stack> #include<algorithm> using namespace std; const int maxn = 1e3 + 10; const int maxm = 330000 + 10; struct EDGE{ int v, nxt; }Edge[maxm]; int Head[maxn], cnt; int DFN[maxn], LOW[maxn],