poj 3694 pku 3694 Network tarjan求割边 lca

题意:给你一个连通图,然后再给你n个询问,每个询问给一个点u,v表示加上u,v之后又多少个桥。一个最容易想到的办法就是先加边找桥,加边找桥,这样可定超时。那么就可以缩点,因为如果一条边不是桥那么无论怎么加边他肯定都不会变成桥,这样我吧不是桥的点缩成一个点。这样全图就都是桥,这样的话,我们就在加的遍里面去找如果加的边是同一个点,那么,肯定不会减少桥,但是如果不是同一个,那么桥肯定减少~。

代码如下:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <stdlib.h>
  6 #include <vector>
  7 #include <queue>
  8 #define loop(s,i,n) for(i = s;i < n;i++)
  9 #define cl(a,b) memset(a,b,sizeof(a))
 10 using namespace std;
 11 const int maxn = 100005;
 12 int low[maxn],dfn[maxn],set[maxn],father[maxn],dfsclock,cut;
 13 vector<int >g[maxn];
 14 int find(int x)
 15 {
 16     if(set[x] != x)
 17     set[x] = find(set[x]);
 18 
 19     return set[x];
 20 }
 21 int merge(int x,int y)
 22 {
 23     x = find(x);
 24     y = find(y);
 25     if(y != x)
 26     {
 27         set[y] = x;
 28         return 1;
 29     }
 30     return 0;
 31 }
 32 
 33 void tarjan(int u,int pre)
 34 {
 35     int v,i,j;
 36     dfn[u] = low[u] = ++dfsclock;
 37     loop(0,i,g[u].size())
 38     {
 39         v = g[u][i];
 40         if(!dfn[v])
 41         {
 42             tarjan(v,u);
 43             father[v] = u;
 44             low[u] = min(low[v],low[u]);
 45             if(low[v] > dfn[u])
 46             cut++;
 47             else
 48             merge(u,v);
 49         }
 50         else if(v != pre)
 51         low[u] = min(low[u],dfn[v]);
 52     }
 53 }
 54 void lca(int u,int v)
 55 {
 56 
 57     while(u != v)
 58     {
 59         while(dfn[u] >= dfn[v] && u != v)
 60         {
 61             if(merge(u,father[u]))
 62             cut--;
 63             u = father[u];
 64         }
 65         while(dfn[v] >= dfn[u] && u != v)
 66         {
 67             if(merge(v,father[v]))
 68             cut--;
 69             v =  father[v];
 70         }
 71     }
 72 }
 73 int main()
 74 {
 75     int n,m;
 76     int i,x,y,cas = 0;
 77     while(scanf("%d %d", &n,&m)&&(n||m))
 78     {
 79         int u,v;
 80         printf("Case %d:
",++cas);
 81         loop(1,i,n+1)
 82         {
 83             g[i].clear();
 84             set[i] = i;
 85             father[i] = 0;
 86         }
 87         while(m--)
 88         {
 89             scanf("%d %d",&u,&v);
 90             g[u].push_back(v);
 91             g[v].push_back(u);
 92 
 93         }
 94         cl(dfn,0);
 95         cl(low,0);
 96         cut = dfsclock = 0;
 97 
 98         int k;
 99         scanf("%d",&k);
100         tarjan(1,-1);
101 
102         while(k--)
103         {
104             scanf("%d %d",&u,&v);
105             lca(u,v);
106             printf("%d
",cut);
107         }
108         puts("");
109     }
110     return 0;
111 }
View Code
原文地址:https://www.cnblogs.com/0803yijia/p/3227711.html