poj 3694 Network : o(n) tarjan + O(n) lca + O(m) 维护 总复杂度 O(m*q)
- /**
- problem: http://poj.org/problem?id=3694
- 问每加一条边后剩下多少桥
- 因为是无向图,所以使用tarjan缩点后会成一棵树并维护pre数组
- 在树上连一条边(a,b)减少的桥数就是
- a点到a点和b点的最近公共祖先(lca)的所有边+b点到a点和b点的最近公共祖先的所有边
- 在算桥的同时将这些点缩成一个点
- 即每个点color = 最近公共祖先color
- 同时维护pre数组 每个点的pre = 最近公共祖先的pre 即可
- **/
- #include<stdio.h>
- #include<stack>
- #include<queue>
- #include<algorithm>
- using namespace std;
- const int MAXN = ;
- const int MAXM = ;
- class Graphics{
- private:
- struct Edge{
- int to, next;
- bool bridge;
- }edge[MAXM];
- struct Point{
- int dfn, low, color;
- }point[MAXN];
- int first[MAXN], pre[MAXN], sign, sumOfPoint, dfnNum, colorNum, bridge;
- bool vis[MAXN];
- stack<int> stk;
- queue<int> bfs;
- void tarjan(int u, int preEdge = -){
- point[u].low = dfnNum;
- point[u].dfn = dfnNum ++;
- vis[u] = true;
- stk.push(u);
- for(int i = first[u]; i != -; i = edge[i].next){
- int to = edge[i].to;
- if((i^) == preEdge) continue;
- if(!point[to].dfn){
- pre[to] = u; ///如果下一个点没被访问过则更新一下下个点的pre
- tarjan(to, i);
- point[u].low = min(point[u].low, point[to].low);
- if(point[to].low > point[u].dfn){
- edge[i].bridge = true;
- edge[i^].bridge = true;
- bridge ++;
- }
- }else if(vis[to]){
- point[u].low = min(point[to].dfn, point[u].low);
- }
- }
- if(point[u].dfn == point[u].low){
- vis[u] = false;
- point[u].color = ++ colorNum;
- while(stk.top() != u){
- pre[stk.top()] = pre[u]; ///缩点时,该环中的所有点pre等于时间戳最小点的pre
- point[stk.top()].color = colorNum;
- vis[stk.top()] = false;
- stk.pop();
- }
- stk.pop();
- }
- }
- public:
- void clear(int n){
- sumOfPoint = n;
- for(int i = ; i <= n; i ++){
- first[i] = -;
- pre[i] = -;
- vis[i] = ;
- point[i].dfn = ;
- }
- sign = colorNum = bridge = ;
- dfnNum = ;
- while(!stk.empty()) stk.pop();
- }
- void addEdgeOneWay(int u, int v){
- edge[sign].to = v;
- edge[sign].next = first[u];
- edge[sign].bridge = false;
- first[u] = sign ++;
- }
- void addEdgeTwoWay(int u, int v){
- addEdgeOneWay(u, v);
- addEdgeOneWay(v, u);
- }
- void tarjanAllPoint(){
- for(int i = ; i <= sumOfPoint; i ++){
- if(!point[i].dfn)
- tarjan(i);
- }
- }
- int getAns(int a, int b){
- for(int i = ; i <= colorNum; i ++){
- vis[i] = false;
- }
- vis[point[a].color] = true;
- vis[point[b].color] = true;
- int lca, lcacolor, ta = a, tb = b;
- while(true){
- if(ta != -) ta = pre[ta];
- if(tb != -) tb = pre[tb];
- if(vis[point[ta].color]){
- lcacolor = point[ta].color;
- lca = ta;
- break;
- }
- if(vis[point[tb].color]){
- lcacolor = point[tb].color;
- lca = tb;
- break;
- }
- vis[point[ta].color] = true;
- vis[point[tb].color] = true;
- }
- while(point[a].color != lcacolor){
- for(int i = first[a]; i != -; i = edge[i].next){
- int to = edge[i].to;
- if(to == pre[a] && edge[i].bridge){
- bridge --;
- edge[i].bridge = false;
- edge[i^].bridge = false;
- break;
- }
- }
- point[a].color = lcacolor;
- int tmp = pre[a];
- pre[a] = pre[lca];
- a = tmp;
- }
- while(point[b].color != lcacolor){
- for(int i = first[b]; i != -; i = edge[i].next){
- int to = edge[i].to;
- if(to == pre[b] && edge[i].bridge){
- bridge --;
- edge[i].bridge = false;
- edge[i^].bridge = false;
- break;
- }
- }
- point[b].color = lcacolor;
- int tmp = pre[b];
- pre[b] = pre[lca];
- b = tmp;
- }
- addEdgeTwoWay(a, b);
- return bridge;
- }
- }graph;
- int main(){
- int n, m, cas = ;
- while(scanf("%d%d", &n, &m) != EOF && m + n){
- graph.clear(n);
- while(m --){
- int a, b;
- scanf("%d%d", &a, &b);
- graph.addEdgeTwoWay(a, b);
- }
- graph.tarjanAllPoint();
- int q;
- scanf("%d", &q);
- printf("Case %d:\n", cas ++);
- while(q --){
- int a, b;
- scanf("%d%d", &a, &b);
- printf("%d\n", graph.getAns(a, b));
- }
- putchar('\n');
- }
- return ;
- }
poj 3694 Network : o(n) tarjan + O(n) lca + O(m) 维护 总复杂度 O(m*q)的更多相关文章
- POJ 3694 Network(无向图求桥+重边处理+LCA)
题目大意: 给你一个无向图,然后再给你一个Q代表有Q次询问,每一次加一条边之后还有几座桥.在这里要对重边进行处理. 每次加入一条边之后,在这条搜索树上两个点的公共祖先都上所有点的桥都没了. 这里重边的 ...
- 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 1236 Network of Schools (Tarjan)
题目链接: Poj 1236 Network of Schools 题目描述: 有n个学校,学校之间有一些单向的用来发射无线电的线路,当一个学校得到网络可以通过线路向其他学校传输网络,1:至少分配几个 ...
- POJ 3694 Network (tarjan + LCA)
题目链接:http://poj.org/problem?id=3694 题意是给你一个无向图n个点,m条边,将m条边连接起来之后形成一个图,有Q个询问,问将u和v连接起来后图中还有多少个桥. 首先用t ...
- POJ 3694 Network(Tarjan求割边+LCA)
Network Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10969 Accepted: 4096 Descript ...
- poj 3694 Network 【Tarjan】+【LCA】
<题目链接> 题目大意: 给一个无向图,该图只有一个连通分量.然后查询q次,q < 1000, 求每次查询就增加一条边,求剩余桥的个数. 解题分析: 普通的做法就是在每加一条边后,都 ...
- poj 3694 Network(双连通分量)
题目:http://poj.org/problem?id=3694 #include <iostream> #include <cstring> #include <cs ...
- poj 3694 Network(割边+lca)
题目链接:http://poj.org/problem?id=3694 题意:一个无向图中本来有若干条桥,有Q个操作,每次加一条边(u,v),每次操作后输出桥的数目. 分析:通常的做法是:先求出该无向 ...
随机推荐
- HashMap put、get方法源码分析
HashMap.java的实现是面试必问的问题. JDK版本 java version "1.8.0_91" Java(TM) SE Runtime Environment (bu ...
- scss-@while指令
@while是一个循环指令,其后跟着一个表达式,如果表达式的返回值为false,则停止循环. scss代码实例如下: $i: 6; @while $i > 0 { .item-#{$i} { w ...
- ActiveMQ VirtualTopic
参考网址: http://activemq.apache.org/virtual-destinations.html http://blog.csdn.net/kimmking/article/det ...
- xshell连不上虚拟机linux的解决办法
1.找到Linux系统的ip地址 输入命令 ifconfig 2.打开本地网络连接 将VMnet1的ip地址设置为和虚拟机ip同一网段的ip 比如虚拟机Linux系统的ip为 192.168. ...
- 【起航计划 036】2015 起航计划 Android APIDemo的魔鬼步伐 35 App->Service->Messenger Service Messenger实现进程间通信
前面LocalService 主要是提供同一Application中组件来使用,如果希望支持不同应用或进程使用Service.可以通过Messenger.使用Messgener可以用来支持进程间通信而 ...
- sql产生流水号
一个产生流水号(年月日+5位流水号)的存储过程 现在客户有一个需求,要产生一个流水号,如090611+000001(年月日+五位流水号),此流水号在数据库表中是主键,且为varchar类 型.如果在当 ...
- Windows7建立无线热点
很实用的技巧,加以记录. 最初我是想使用connectify的,不过安装这个软件之后,发现有线账号登不上了,所以就选择使用Windows7自带的工具了. 首先以管理员身份运行cmd. 进入之后cd到c ...
- collectd配置
udp proxy - 192.168.48.112 cat > /etc/collectd_25801.conf << EOF Hostname "kvm-48-112& ...
- SqlServer50条常用查询语句
Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 问题 ...
- Python 调度算法 死锁 静动态链接(七)
1 select poll epoll的区别 基本上select有3个缺点: 连接数受限 查找配对速度慢 数据由内核拷贝到用户态 poll改善了第一个缺点 epoll改了三个缺点. (1)select ...