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

题意:n个点,m条边,给你一个连通图,然后有Q次操作,每次加入一条边(A,B),加入边后,问当前还有多少桥,输出桥的个数。

解题思路:先将原连通图边双连通缩点成一颗树,Q次操作过程中对树进行LCA操作。具体看代码:

看网上也有不缩点的方法。

思路参考于:http://www.cnblogs.com/kuangbin/p/3184884.html

#include "stdio.h"   //poj 3177 边双连通问题 + LCA(最近公共祖先)
#include "string.h"
#include "vector"
#include "queue"
using namespace std; #define N 100100
#define M 400200 struct node
{
int x,y;
bool visit;
int next;
} edge[2*M];
int idx,head[N]; void Init()
{
idx = 0;
memset(head,-1,sizeof(head));
} void Add(int x,int y)
{
edge[idx].x = x;
edge[idx].y = y;
edge[idx].visit = false;
edge[idx].next = head[x];
head[x] = idx++;
} int time;
int low[N],dfn[N];
inline int MIN(int a,int b)
{
return a<b?a:b;
} int st[M],num; //记录哪些点为桥
int stackk[2*M],top; //模拟栈(本题栈中存的是点,不是边) int n,m;
int countt; //记录有多少个双连通分量
int belong[N]; void lian_tong(int x)
{
int t;
countt++;
while(1)
{
t = stackk[top];
top--;
belong[t] = countt;
if(t==x) break;
}
} void DFS(int x)
{
int i,y;
stackk[++top] = x;
low[x] = dfn[x] = ++time;
for(i=head[x]; i!=-1; i=edge[i].next)
{
y = edge[i].y;
if(edge[i].visit) continue;
edge[i].visit = edge[i^1].visit = true;
if(!dfn[y])
{
DFS(y);
low[x] = MIN(low[x],low[y]);
if(low[y]>dfn[x])
st[num++] = i; //记录桥(两边双连通分量必定由桥相连)
}
else
low[x] = MIN(low[x],dfn[y]);
}
if(dfn[x]==low[x])
lian_tong(x); //标记当前边双连通分量
} int ans;
bool mark[N];
int deep[N];
int father[N];
vector<int> vec[N]; //存树 void LCA_bfs(int root)
{
int i,x,y;
memset(deep,-1,sizeof(deep));
deep[root] = 0;
mark[root] = false;
father[root] = -1;
queue<int> q;
q.push(root);
while(!q.empty())
{
x = q.front();
q.pop();
for(i=0; i<(int)vec[x].size(); ++i)
{
y = vec[x][i];
if(deep[y]!=-1) continue;
deep[y] = deep[x]+1;
mark[y] = true;
father[y] = x;
q.push(y);
}
}
} void swap(int &x,int &y)
{
int t = x;
x = y;
y = t;
} void LCA(int x,int y)
{
if(deep[x] > deep[y]) swap(x,y);
while(deep[x]<deep[y])
{
if(mark[y])
{
ans--;
mark[y] = false;
}
y = father[y];
}
while(x!=y)
{
if(mark[x])
{
ans--;
mark[x] = false;
}
if(mark[y])
{
ans--;
mark[y] = false;
}
x = father[x];
y = father[y];
}
} void Solve()
{
int i;
int x,y;
countt = 0; //统计边双连通分量的个数
num = 0; //统计桥的条数
top = 0; //栈
time = 0;
memset(dfn,0,sizeof(dfn));
DFS(1);
for(i=1; i<=countt; ++i) vec[i].clear();
for(i=0; i<num; ++i) //遍历桥
{
x = edge[st[i]].x;
y = edge[st[i]].y;
x = belong[x];
y = belong[y];
vec[x].push_back(y);
vec[y].push_back(x);
}
LCA_bfs(1);
ans = countt - 1;
int Q;
int u,v;
scanf("%d",&Q);
while(Q--)
{
scanf("%d %d",&u,&v);
LCA(belong[u],belong[v]);
printf("%d\n",ans);
}
printf("\n");
} int main()
{
int i;
int Case=0;
int x,y;
while(scanf("%d %d",&n,&m),n+m)
{
Init();
Case++;
for(i=0; i<m; ++i)
{
scanf("%d %d",&x,&y);
Add(x,y);
Add(y,x);
}
printf("Case %d:\n",Case);
Solve();
}
return 0;
}

poj 3694 Network 边双连通+LCA的更多相关文章

  1. POJ 3694 Network 无向图双联通+LCA

    一开始题目没看清楚,以为是增加那条边后还有多少桥,所以就当做是无向图tarjan缩点后建树,然后求u,v的最近公共祖先,一直wa. 后来再看题目后才发现边放上去后不会拿下来了,即增加i条边后桥的数量. ...

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

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

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

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

  4. poj 3694 Network(双连通分量)

    题目:http://poj.org/problem?id=3694 #include <iostream> #include <cstring> #include <cs ...

  5. POJ 3694 Network(Tarjan求割边+LCA)

    Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10969   Accepted: 4096 Descript ...

  6. [双连通分量] POJ 3694 Network

    Network Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9434   Accepted: 3511 Descripti ...

  7. (中等) CF 555E Case of Computer Network,双连通+树。

    Andrewid the Android is a galaxy-known detective. Now he is preparing a defense against a possible a ...

  8. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  9. poj 3694 Network(割边+lca)

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

随机推荐

  1. 常见的几种 CSS 水平垂直居中解决办法

    用CSS实现元素的水平居中,比较简单,可以设置text-align center,或者设置 margin-left:auto; margin-right:auto 之类的即可. 主要麻烦的地方还是在垂 ...

  2. C#中this的 四种 用法

    C#中的this用法,相信大家应该有用过,但你用过几种?以下是个人总结的this几种用法,欢迎大家拍砖,废话少说,直接列出用法及相关代码. this用法1:限定被相似的名称隐藏的成员 /// < ...

  3. 剑指offer面试题31连续子数组的最大和

    一.题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果 ...

  4. 2 Orchard汉化资源包的使用

    Orchard安装完毕之后我们就可以在后台尝试做一些基本的操作感受下Orchard提供的一些功能,比如添加一个页面.菜单.文章什么的.也可以试着新建一些部件.布局之类的感受下.个人建议摆弄一下了解下就 ...

  5. csharp:百度翻译

    参考:http://api.fanyi.baidu.com/api/trans/product/index http://developer.baidu.com/wiki/index.php?titl ...

  6. csharp: Export or Import excel using NPOI

    excel 2003: using System; using System.Collections.Generic; using System.ComponentModel; using Syste ...

  7. [转]PDO防注入原理分析以及使用PDO的注意事项

    原文:http://zhangxugg-163-com.iteye.com/blog/1835721 好文章不得不转. 我们都知道,只要合理正确使用PDO,可以基本上防止SQL注入的产生,本文主要回答 ...

  8. Java Web Cookie

    一.什么是cookie? 1.Cookie能使站点跟踪特定访问者的访问次数.最后访问时间和访问者进入站点的路径 2.Cookie能告诉在线广告商广告被点击的次数,从而可以更精确的投放广告 3.Cook ...

  9. Java多线程--wait(),notify(),notifyAll()的用法

    忙等待没有对运行等待线程的 CPU 进行有效的利用(而且忙等待消耗cpu过于恐怖,请慎用),除非平均等待时间非常短.否则,让等待线程进入睡眠或者非运行状态更为明智,直到它接收到它等待的信号. Java ...

  10. 一个SpringMVC简单Demo中出现的错误

    最近在学springmvc 一个简答的Springmvc配置包括如下步骤: 1.在 web.xml 文件中配置 DispatcherServlet (该中央控制器相当于 MVC 模式中的 C),还可以 ...