zoukankan      html  css  js  c++  java
  • POJ

    题意:给出一个无相图,然后q次新增加边,问在添加边的过程中桥的数目
    当且仅当无向边(u,v)为树枝的时候,需要满足dfn(u)<low(v),
    也就是v向上翻不到u及其以上的点,那么u-v之间一定能够有1条或者多条边不能删去,因为他们之间有一部分无环,是桥
    思路:首先我们知道在给定一张图之后,不断添加边,桥的数目只会减少而不是增加
    tarjan的使用就是缩点,将一个连通分量缩成一个点,那么那个连通分量中的边都不会是桥
    同时缩完点之后我们就会发现,桥其实就是新形成的树的边
    在添加的过程中,如果是在连通分量内就不会减少桥的数目
    如果是u,v在两个不同的连通分量中,那么u,v以及其lca(最小公共祖先)就会连成一个回路,就形成了一个新的连通分量
    那么被连接的这整个一段部分的所有桥的数目就会减少

    完整代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #define IOS ios::sync_with_stdio(0); cin.tie(0); using namespace std; typedef long long LL; typedef pair<int,int>pii; const double eps = 1e-8; const int inf = 0x3f3f3f3f; const int maxn = 1e5+10; const int max_edge = 4e5+5; struct Edge { int to, next; }edge[max_edge]; int top, head[maxn]; int pre[maxn]; int id, dfn[maxn], low[maxn]; int cnt; int bridge[maxn]; int n,m; void add(int u,int v){ edge[top].to = v; edge[top].next = head[u]; head[u] = top++; } void tarjan(int x,int f){ //更新时间戳 dfn[x] = low[x] = ++id; for(int i = head[x]; ~i;i = edge[i].next){ int v = edge[i].to; if(!dfn[v]){ tarjan(v,x); pre[v] = x; low[x] = min(low[v],low[x]); //桥的判定条件 if(low[v]>dfn[x]){ bridge[v] = 1; cnt++; } } else if(v != f){ low[x] = min(low[x],dfn[v]); } } } void init(){ memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(bridge,0,sizeof(bridge)); memset(head,-1,sizeof(head)); cnt = id = top = 0; } void lca(int u,int v){ //进入时交换一下,把根赋值给u if(dfn[u] < dfn[v]) swap(u,v); //先将底的一边走到同样的高度 while(dfn[u] > dfn[v]){ if(bridge[u]) cnt--,bridge[u]=0; u = pre[u]; } //两边同时向lca走 while(u != v){ if(bridge[u]) cnt--,bridge[u] = 0; if(bridge[v]) cnt--,bridge[v] = 0; u = pre[u]; v = pre[v]; } } int main(){
       //IOS (加速cin可以少一倍时间)
    int Case = 0; while(cin>>n>>m&&n&&m){ init(); for(int i =0;i<m;i++){ int u,v; cin>>u>>v; add(u,v),add(v,u); } tarjan(1,1); int q; cin>>q; cout<<"Case "<<++Case<<":"<<endl; while(q--){ int u,v; cin>>u>>v; lca(u,v); cout<<cnt<<endl; } } return 0; }
  • 相关阅读:
    zhcon安装过程记录
    diff和patch配合使用(转载备用)
    Linux /etc/passwd 和 /etc/group 文件格式
    APT 常用功能
    Linux邮件服务器架构
    出现segment fault 错误的几种原因
    位运算
    Linux启动过程中几个重要配置文件的执行过程
    2016-2017 ACM-ICPC, South Pacific Regional Contest (SPPC 16)
    Codeforces Round #439 (Div. 2) 题解
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11328947.html
Copyright © 2011-2022 走看看