Sol - P7687

本题考查知识点是割点和桥以及对 tarjan 算法的理解。

根据题意或者根据样例,我们不难得出两个结论:

  • 是关键通信线路的一定是桥,桥不一定是关键通信线路;

  • 满足条件的桥一定会使有一个连通块不存在含服务 \(A\) 的点或服务 \(B\) 的点。

因此,在 tarjan 的过程中,为关键通信线路的边需要满足下列两个条件:

  • 该边为桥;

  • 在 DFS 子树里,服务 \(A\) 数量为 \(0\)\(K\),或服务 \(B\) 数量为 \(0\)\(L\)

于是这道题就解决了。

tarjan 代码如下。

void tarjan(int u,int fa){
    dfn[u]=low[u]=++Cnt;
    for(int v:e[u]){
        if(v==fa)continue;
        if(!dfn[v]){
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u] && (!a[v] || !b[v] || a[v]==k || b[v]==l)){
                //这条边是桥,且子树中要么占据所有 A 或 B 服务,要么一个 A 或 B 服务都没有
                ans.push_back(make_pair(u,v));
            }
            a[u]+=a[v]; b[u]+=b[v];
        }else low[u]=min(low[u],dfn[v]);
    }
}
posted @ 2023-11-09 14:48  MC铁锭233  阅读(9)  评论(0编辑  收藏  举报