题目链接: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. Python 3.x自定义迭代器对象

    Python 3.x与Python 2.x之间存在着较多的语法细节差异.今天在看Python核心编程的时候,说到了自定义迭代器对象.于是动手将源码打了一遍,原书代码如下: class AnyIter( ...

  2. thread_CyclicBarrier回环栅栏

    CyclicBarrier回环栅栏,字面意思是可循环使用(Cyclic)的屏障(Barrier).通过它可以实现让一组线程等待至某个状态之后再全部同时执行. 它要做的事情是,让一组线程到达一个屏障(也 ...

  3. 【原创】本地通过IIS设置开发的localhost网站的域名改为个性域名方法

    效果图:   操作步骤如下:  第一步: 在本地IIS上新建个网站,如下图所示      第二步,修改host文件       加配置节点如下图所示       第三步,在vs里面找到你的web项目, ...

  4. c# dynamic动态类型和匿名类

    dynamic类型 简单示例 dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写 expando.Id = 1; e ...

  5. WPF 竖排文字

    ---恢复内容开始--- 想做一个WPF 文字竖排 类似上图.用在TabItem的header上面. <TextBlock FontSize="30" Text=" ...

  6. Dev gridView中设置自适应列宽和日期显示格式、金额的显示格式

    在Dev GridView控件中,数据库中表数据日期都是长日期格式(yyyy-MM-dd HH:mm:ss),但显示在控件变成短日期格式(yyyy-MM-dd),金额显示要显示精确的数值, 比如80. ...

  7. hibernate初步4

    JPA 1.JPA概述 JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据.,而Hi ...

  8. android Adapter剖析理解

    UI控件都是跟Adapter(适配器)打交道的 Adapter: 是用来帮助控件填充数据的中间桥梁 (在开发中大多数Textview控件的内容是依靠数据库传递并显示的如:新闻类) Adapter: 将 ...

  9. EntityFramework嵌套查询的五种方法

    这样的双where的语句应该怎么写呢: var test=MyList.Where(a => a.Flows.Where(b => b.CurrentUser == “”) 下面我就说说这 ...

  10. Enforcing the correct protocol for partially SSL secured SharePoint sites

    Enforcing the correct protocol for partially SSL secured SharePoint sites http://www.sharepointconfi ...