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 }
View Code

 

posted @ 2017-08-02 17:04  geloutingyu  阅读(351)  评论(0编辑  收藏  举报