题意:有N台电脑,他们之间有M条无向边。

然后询问,每次在他们之间加一条边,剩余的桥有多少。

思路:其实这题都不需要缩点了。。

直接记录每条桥的位置,然后每次询问进行一次LCA,当询问到桥时,桥数减1,下次询问就不会再计数了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2505
#define inf 1<<28
#define LL(x) ( x << 1 )
#define RR(x) ( x << 1 | 1 )
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define PII pair<int,int>
using namespace std;
#define M 500005
#define N 200005
#define stop system("pause")
inline void RD(int &ret) {
char c;
do {
c = getchar();
} while(c < '0' || c > '9') ;
ret = c - '0';
while((c=getchar()) >= '0' && c <= '9')
ret = ret * 10 + ( c - '0' );
}
struct edge {
int e , next , sign ;
} ed[M] ; struct Bridge {
int s ,e ;
} bridge[M] ;
int n , m ;
int head[N] ,num ;
int dfn[N] , low[N] ,st[N] ,inst[N] , belong[N] ;
int dp ,top ,cnt ;
int bridgenum ;
int isBridge[N] ;
int faa[N] ;
void add(int s ,int e) {
ed[num].e = e ;
ed[num].sign = 0 ;
ed[num].next = head[s] ;
head[s] = num ++ ;
} void init() {
mem(dfn, 0) ;
mem(low , 0) ;
mem(st ,0) ;
mem(belong ,0) ;
mem(head, -1) ;
num = 0 ;
dp = 0 ;
top = 0 ;
cnt = 0 ;
bridgenum = 0 ;
mem(isBridge , 0) ;
} void tarjan(int now ,int fa) {
dfn[now] = low[now] = ++ dp ;
st[top ++ ] = now ;
inst[now] = 1 ;
faa[now] = fa ;
for (int i = head[now] ; ~i ; i = ed[i].next ) {
if(ed[i].sign)continue ;
ed[i].sign = ed[i ^ 1].sign = 1 ;
int e = ed[i].e ;
if(!dfn[e]) {
tarjan(e , now) ;
low[now] = min(low[now] ,low[e]) ;
if(dfn[now] < low[e]) {
bridge[bridgenum].s = now ;
bridge[bridgenum ++ ].e = e ;
isBridge[e] = 1 ;
}
} else if(inst[e]) {
low[now] = min(low[now] , dfn[e]) ;
}
}
if(low[now] == dfn[now]) {
int xx ;
cnt ++ ;
do {
xx = st[-- top] ;
inst[xx] = 0 ;
belong[xx] = cnt ;
} while(xx != now) ;
}
}
void read() {
init() ;
while(m -- ) {
int a , b ;
RD(a) ;
RD(b) ;
add(a , b) ;
add(b , a) ;
}
for (int i = 1 ; i <= n ; i ++ ) {
dp = 0 ,top = 0 ;
if(!dfn[i])tarjan(i , -1) ;
}
}
void LCA(int u ,int v) {
if(dfn[u] < dfn[v]) swap(u , v) ;
while(dfn[u] > dfn[v]) {
if(isBridge[u]) -- bridgenum , isBridge[u] = 0 ;
u = faa[u] ;
}
while(u != v) {
if(isBridge[u])-- bridgenum ,isBridge[u] = 0 ;
u = faa[u] ;
if(isBridge[v])-- bridgenum ,isBridge[v] = 0 ;
v = faa[v] ;
}
} void solve() {
read() ;
int Q ;
RD(Q) ;
while( Q -- ) {
int a , b ;
RD(a) ;
RD(b) ;
if(belong[a] != belong[b])
LCA(a , b) ;
printf("%d\n",bridgenum) ; }
}
int main() {
int cas = 0 ;
while(scanf("%d%d",&n ,&m) ,(n + m )) {
printf("Case %d:\n",++ cas) ;
solve() ;
puts("") ;
}
return 0 ;
}

POJ 3694 LCA的更多相关文章

  1. Network POJ - 3694 (LCA+tarjan+桥)

    题目链接:https://vjudge.net/problem/POJ-3694 具体思路:首先可以通过缩点的方式将整个图变成一个树,并且树的每条边是桥,但是我们可以利用dfn数组将整个图变成树,这样 ...

  2. 【POJ 3694】 Network(割边&lt;桥&gt;+LCA)

    [POJ 3694] Network(割边+LCA) Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7971 ...

  3. POJ 3694——Network——————【连通图,LCA求桥】

    Network Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  4. Poj 3694 Network (连通图缩点+LCA+并查集)

    题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条 ...

  5. Tarjan算法各种&RMQ& POJ 3694

    关于tarjan 的思想可以在网上搜到,具体我也不太清楚,应该说自己理解也不深,下面是做题经验得到的一些模板. 其中有很多转载,包括BYVoid等,感谢让我转...望各路大神愿谅 有向图求连通分量的一 ...

  6. poj 3694 Network 边双连通+LCA

    题目链接:http://poj.org/problem?id=3694 题意:n个点,m条边,给你一个连通图,然后有Q次操作,每次加入一条边(A,B),加入边后,问当前还有多少桥,输出桥的个数. 解题 ...

  7. POJ 3694 Network (tarjan + LCA)

    题目链接:http://poj.org/problem?id=3694 题意是给你一个无向图n个点,m条边,将m条边连接起来之后形成一个图,有Q个询问,问将u和v连接起来后图中还有多少个桥. 首先用t ...

  8. poj 3694 Network(割边+lca)

    题目链接:http://poj.org/problem?id=3694 题意:一个无向图中本来有若干条桥,有Q个操作,每次加一条边(u,v),每次操作后输出桥的数目. 分析:通常的做法是:先求出该无向 ...

  9. poj 3694 Network : o(n) tarjan + O(n) lca + O(m) 维护 总复杂度 O(m*q)

    /** problem: http://poj.org/problem?id=3694 问每加一条边后剩下多少桥 因为是无向图,所以使用tarjan缩点后会成一棵树并维护pre数组 在树上连一条边(a ...

随机推荐

  1. Android实现程序前后台切换效果

    本文演示如何在Android中实现程序前后台切换效果. 在介绍程序实现之前,我们先看下Android中Activities和Task的基础知识. 我们都知道,一个Activity 可以启动另一个Act ...

  2. Hacker(23)----破解常见文件密码

    Win7中,office文档.压缩文件等都是常见的文件,这些文档含有重要的信息,即使用户为这些文件设置了密码,黑客也会有办法破解. 一.破解office文档密码 破解office文档密码常用工具是Ad ...

  3. java基础之String

    字符串的含义 字符串的应用 字符串的方法

  4. 开始学javascript基础

    JavaScript非常值得我们学习. 1)所有主浏览器都支持JavaScript. 2) 目前,全世界大部分网页都使用JavaScript. 3) 它可以使网页呈现各种动态效果. 4)作为一个Web ...

  5. 《第一行代码》学习笔记12-UI(1)

    1.程序需要注销或者退出,用一个专门的集合类对所有的活动进行管理即可. 2.可视化编辑工具不利于真正了解界面背后的实现原理,通常这种方式制作的界面都不具有很好的屏幕适配性, 而且当需要编写较为复杂的界 ...

  6. 数据泵导出/导入Expdp/impdp

    一下转自 http://blog.csdn.net/jionjionyoushen/article/details/6789686 数据泵导出/导入Expdp/impdp Oracle 10g引入了D ...

  7. (原)torch7中添加新的层

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6069627.html 参考网址: http://torch.ch/docs/developer-doc ...

  8. Jquery 中 $('obj').attr('checked',true)失效的几种解决方案

    转载自:搜狐博客 大拙无为 1.$('obj').prop('checked',true) 2. $(':checkbox').each(function(){ this.checked=true; ...

  9. Effective Java2读书笔记-对于所有对象都通用的方法(一)

    第8条:覆盖equals时请遵守通用约定 ①约定的内容 自反性.对于任何非null的引用值x.x.equals(x)必须返回true. 对称性.对于任何非null的引用值x和y.当且仅当y.equal ...

  10. 用php理解指针--写给刚刚学习编程的人

    在刚刚学习编程时,可能for循环什么的还是可以理解,但是当学习到指针的时候,课上估计很多人就睡觉去了. 现在用两端php程序说明指针 先写一个简单的,大家都理解下 <?php class tex ...