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

Description

A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are connected directly or indirectly by successive links, so data can be transformed between any two computers. The administrator finds that some links are vital to the network, because failure of any one of them can cause that data can't be transformed between some computers. He call such a link a bridge. He is planning to add some new links one by one to eliminate all bridges.

You are to help the administrator by reporting the number of bridges in the network after each new link is added.

Input

The input consists of multiple test cases. Each test case starts with a line containing two integers N(1 ≤ N ≤ 100,000) and M(N - 1 ≤ M ≤ 200,000).
Each of the following M lines contains two integers A and B ( 1≤ A ≠ B ≤ N), which indicates a link between computer A and B. Computers are numbered from 1 to N. It is guaranteed that any two computers are connected in the initial network.
The next line contains a single integer Q ( 1 ≤ Q ≤ 1,000), which is the number of new links the administrator plans to add to the network one by one.
The i-th line of the following Q lines contains two integer A and B (1 ≤ A ≠ B ≤ N), which is the i-th added new link connecting computer A and B.

The last test case is followed by a line containing two zeros.

Output

For each test case, print a line containing the test case number( beginning with 1) and Q lines, the i-th of which contains a integer indicating the number of bridges in the network after the first i new links are added. Print a blank line after the output for each test case.

Sample Input

3 2
1 2
2 3
2
1 2
1 3
4 4
1 2
2 1
2 3
1 4
2
1 2
3 4
0 0

Sample Output

Case 1:
1
0 Case 2:
2
0

Source

原题大意:输入点的个数N和边的个数M,接下来输入整数Q代表询问的次数,之后Q行有两个整数A,B,表示将A与B相连。问每次询问后割边(桥)的数量。
解题思路1:用tarjian找割边并标记,之后用lca遍历A与B到最近公共祖先的路径,这段路上是割边的处理掉,总数-1就可以了。
                表示用链表写的,各种慢,但是POJ数据太弱了,怎么写都能过。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct list
{
int v;
list *next;
};
list *head[110010],*rear[110010];
int father[110010],times,dfn[110010],low[110010],bridge[110010],bridgenum,n;
int dep[110010];
void init()
{
int i;
memset(head,0,sizeof(head));
memset(dep,0,sizeof(dep));
memset(rear,0,sizeof(rear));
for(i=1;i<=n;++i) father[i]=i;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(bridge,0,sizeof(bridge));
times=bridgenum=0;
}
void insert(int a,int b)
{
if(rear[a]!=NULL)
{
rear[a]->next=new list;
rear[a]=rear[a]->next;
} else head[a]=rear[a]=new list;
rear[a]->v=b;
rear[a]->next=NULL;
return;
}
void tarjian(int v)
{
bool flag=true;
dfn[v]=low[v]=++times;
dep[v]=dep[father[v]]+1;
for(list *p=head[v];p!=NULL;p=p->next)
{
if(p->v==father[v]&&flag)
{
flag=false;
continue;
}
if(!dfn[p->v])
{
father[p->v]=v;
tarjian(p->v);
low[v]=min(low[v],low[p->v]);
if(low[p->v]>dfn[v])
{
++bridgenum;
bridge[p->v]=1;
}
}else low[v]=min(low[v],dfn[p->v]);
}
}
void lca(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
while(dep[a]!=dep[b])
{
if(bridge[a])
{
bridge[a]=0;
--bridgenum;
}
a=father[a];
}
while(a!=b)
{
if(bridge[a])
{
bridge[a]=0;
--bridgenum;
}
if(bridge[b])
{
bridge[b]=0;
--bridgenum;
}
a=father[a];
b=father[b];
}
return;
}
int main()
{
int m,i,a,b,q,ccase=0;
while(~scanf("%d%d",&n,&m),n&&m)
{
init();
for(i=0;i<m;++i)
{
scanf("%d%d",&a,&b);
insert(a,b);insert(b,a);
}
tarjian(1);
scanf("%d",&q);
printf("Case %d:\n",++ccase);
for(i=1;i<=q;++i)
{
scanf("%d%d",&a,&b);
lca(a,b);
printf("%d\n",bridgenum);
}
}
return 0;
}

解题思路2:在原来的基础上用并查集优化,这种做法是看了大神们的解题思路写出的。

将双连通的两个点弄成一个集合,这样在LCA时只要判断是否是一个集合,将桥的数量减去即可。

#include<stdio.h>
#include<string.h>
struct list
{
int v;
list *next;
};
list *head[111010],*rear[111010];
int n,m,father[111010],dep[110010],low[110010],fath[110010],bridgenum;
void init()
{
int i;
memset(head,0,sizeof(head));
memset(rear,0,sizeof(rear));
memset(dep,0,sizeof(dep));
memset(low,0,sizeof(low));
memset(fath,0,sizeof(fath));
for(i=1;i<=n;++i) father[i]=i;
bridgenum=0;
}
void insert(int a,int b)
{
if(rear[a]!=NULL)
{
rear[a]->next=new list;
rear[a]=rear[a]->next;
} else head[a]=rear[a]=new list;
rear[a]->v=b;
rear[a]->next=NULL;
}
int find(int x)
{
return father[x]==x?x:father[x]=find(father[x]);
}
void merge(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy) father[fx]=fy;
}
void tarjian(int v,int deps)
{
bool flag=true;
dep[v]=low[v]=deps;
for(list *p=head[v];p!=NULL;p=p->next)
{
if(p->v==fath[v]&&flag)
{
flag=false;
continue;
}
if(!dep[p->v])
{
fath[p->v]=v;
tarjian(p->v,deps+1);
if(low[v]>low[p->v]) low[v]=low[p->v];
if(low[p->v]<=dep[v]) merge(p->v,v);
else bridgenum++;
}
else if(low[v]>dep[p->v]) low[v]=dep[p->v];
}
}
void judge(int v)
{
int x=find(v);
int y=find(fath[v]);
if(x!=y)
{
--bridgenum;
father[x]=y;
}
}
void lca(int u,int v)
{
while(dep[u]>dep[v])
{
judge(u);
u=fath[u];
}
while(dep[u]<dep[v])
{
judge(v);
v=fath[v];
}
while(u!=v)
{
judge(u);judge(v);
u=fath[u];v=fath[v];
}
}
int main()
{
int a,b,q,num=0;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
init();
while(m--)
{
scanf("%d%d",&a,&b);
insert(a,b);insert(b,a);
}
printf("Case %d:\n",++num);
tarjian(1,1);
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&a,&b);
if(find(a)!=find(b)) lca(a,b);
printf("%d\n",bridgenum);
}
printf("\n");
}
return 0;
}

  

[双连通分量] POJ 3694 Network的更多相关文章

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

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

  2. poj 3694 Network 边双连通+LCA

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

  3. poj 3694 Network(割边+lca)

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

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

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

  5. [双连通分量] POJ 3177 Redundant Paths

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13712   Accepted: 5821 ...

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

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

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

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

  8. POJ 3694 Network (tarjan + LCA)

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

  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. 6.能够使HTML和PHP分离开使用的模板

    Smarty,Dwoo,TinyButStrong,Template Lite,Savant,phemplate,XTemplate

  2. Python快速建站系列-Part.Five.1-个人主页及发表文章

    |版权声明:本文为博主原创文章,未经博主允许不得转载. 现在的TSSS已经有了注册和登录的功能,首页的内容也填充好了,那这一节就完成用户个人主页的内容和发表文章功能的实现. 先完成用户个人主页的use ...

  3. 介绍kali下的一些小工具

    1.macchanger 可以用来修改你的mac地址

  4. Qt之qt4.7 和qt 4.8.4 交叉实践

    开发机环境搭建: 测试环境:CentOs7.1  Ubuntu 12.0.4 操作流程: 一.编译Qt4.7.0 1)CentOS上实践 1.tar xzvf qt-everywhere-openso ...

  5. [转]ASP.NET MVC Json()处理大数据异常解决方法 json maxjsonlength

    本文转自:http://blog.csdn.net/blacksource/article/details/18797055 先对项目做个简单介绍: 整个项目采用微软的ASP.NET MVC3进行开发 ...

  6. this的面面观

    http://www.cnblogs.com/Wayou/p/all-this.html <JavaScript语言精粹> 全局this 浏览器宿主的全局环境中, function f(x ...

  7. MySQL functions, IF, CASE

    MySQLTutorial官网 IF function syntax: IF(expr,if_true_expr,if_false_expr) CASE expression syntax: CASE ...

  8. ipad开发:二维码扫描,摄像头旋转角度问题解决办法

    之前一直是在手机上开发,用系统原生二维码扫描功能,一点问题都没有,但是在ipad上,用户是横屏操作的,虽然界面旋转了,是横屏的,但是摄像头里显示的依然是竖屏效果,也就是说从摄像头里看到的和人眼看到的内 ...

  9. R绘图基础

    一,布局 R绘图所占的区域,被分成两大部分,一是外围边距,一是绘图区域. 外围边距可使用par()函数中的oma来进行设置.比如oma=c(4,3,2,1),就是指外围边距分别为下边距:4行,左边距3 ...

  10. ArcGIS10.2中文版破解教程

    ArcGIS10.2中文版前些时间早就出炉了,下载了但是一直没有安装,听说了ArcGIS10.2云处理能力和影像处理能力都增强了!网上经常遇到一些朋友安装失败的问题,现在特此做一个教程!分享一下安装成 ...