• 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
  • 相关阅读:
    让AutoMapper更好用
    设置ADB网络连接目标板
    windos或linux中 which命令 查看当前要执行的命令所在的路径
    secureCRT使用退格键(backspace)出现^H解决办法
    Ubuntu12.04安装insight-6.8
    Linux命令之type
    BUG:给Nexus7编译Android4.2的时候出现 fatal error: map: No such file or directory
    Kconfig和Makefile的修改
    diff命令的参数详解和实例
    Linux获取当前目录名,shell获取当前目录名
  • 原文地址:https://www.cnblogs.com/0803yijia/p/3227711.html
Copyright © 2020-2023  润新知