poj 3694 Network 边双连通+LCA
题目链接: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的更多相关文章
- POJ 3694 Network 无向图双联通+LCA
一开始题目没看清楚,以为是增加那条边后还有多少桥,所以就当做是无向图tarjan缩点后建树,然后求u,v的最近公共祖先,一直wa. 后来再看题目后才发现边放上去后不会拿下来了,即增加i条边后桥的数量. ...
- Poj 3694 Network (连通图缩点+LCA+并查集)
题目链接: Poj 3694 Network 题目描述: 给出一个无向连通图,加入一系列边指定的后,问还剩下多少个桥? 解题思路: 先求出图的双连通分支,然后缩点重新建图,加入一个指定的边后,求出这条 ...
- POJ 3694——Network——————【连通图,LCA求桥】
Network Time Limit:5000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Stat ...
- poj 3694 Network(双连通分量)
题目:http://poj.org/problem?id=3694 #include <iostream> #include <cstring> #include <cs ...
- POJ 3694 Network(Tarjan求割边+LCA)
Network Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10969 Accepted: 4096 Descript ...
- [双连通分量] POJ 3694 Network
Network Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 9434 Accepted: 3511 Descripti ...
- (中等) CF 555E Case of Computer Network,双连通+树。
Andrewid the Android is a galaxy-known detective. Now he is preparing a defense against a possible a ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- poj 3694 Network(割边+lca)
题目链接:http://poj.org/problem?id=3694 题意:一个无向图中本来有若干条桥,有Q个操作,每次加一条边(u,v),每次操作后输出桥的数目. 分析:通常的做法是:先求出该无向 ...
随机推荐
- 移动端前端常见的触摸相关事件touch、tap、swipe等整理
前端的很多事件在PC端和浏览器端可公用,但有些事件却只在移动端产生,如触摸相关的事件 本文整理了移动端常见的一些事件,包括原生支持的click.touch.tap.swipe事件,也有定义型的gest ...
- 译:Datetime类型的扩展
译文出处:http://www.codeproject.com/Articles/870939/Datetime-Extensions 本文主要针对System.DateTime类型的一系列扩展.包括 ...
- ASP.NET MVC传送参数至服务端
ASP.NET MVC传送参数至服务端,前端与服务端的写法,你可以参考与采用适合你的需求的.当你只传递一两个参数也许觉得没有什么,如果一个方法中带的参数多的话,可以考虑model,前端可以考虑对象进行 ...
- linq order by charindex 排序 按给定字符串顺序排序
//list=list.OrderBy(ee => SqlFunctions.CharIndex("书记,主任,支部委员,村委委员,系统工作人员", ee.ZhiWu)).T ...
- display:inline-block兼容ie6/7的写法
2.display:inline-block作用? 使用display:inline-block属性,可以使行内元素或块元素能够变成行内块元素,简单直白点讲就是不加float属性就可以定义自身的宽.高 ...
- 从零开始学习Linux(cp 命令)
功能: 复制文件或目录说明: cp指令用于复制文件或目录,如同时指定两个以上的文件或目录,且最后的目的地是一个已经存在的目录,则它会把前面指定的所有文件或目录复制到此目录中.若同时指定多个文件或目录, ...
- 设置php下载文件的超时时间
使用curl 可以使用curl自己实现一个curl_file_get_contents函数 //CURLOPT_FOLLOWLOCATION TRUE 时将会根据服务器返回 HTTP 头中的 &quo ...
- gcd和拓展gcd算法
gcd算法是用来求两个数最大公约数的算法,他是依靠辗转相除(中国好像叫辗转相减)法来求两个数的最大公约数,别的地方也有很多介绍不做过多赘述,主要提供代码供自己参考. gcd(int a,int b) ...
- PHP imagecopyresampled 参数图示
- .Net开发人员有趣的Podcast
如果你是一个.Net开发人员,那么一定不要错过这些Podcasts,它们可是即可以了解IT业态,又可以锻炼英文听力.有采访很多开源人员,涉及项目等等.先尽力听他们说什么,然后再看Tra ...