Educational Codeforces Round 46 (Rated for Div. 2) E. We Need More Bosses 图论 桥

题目链接: E. We Need More Bosses

题目大意:

一个无向图, n个节点, m条边,选择两个节点s和t, 使得从s到t所有路径中都出现的边的数量最大(从s到t无论怎么走都必须要经过这些边)

思路

无向图中,在两点间所有路径出现的边为无向图的桥, 将所有非桥边的权值设为0, 桥的权值设为1(即将边双联通分量缩成一个点),求得出的无向图最长路径,即为答案

桥与割点

  • 定义:

    1. 无向连通图中,如果某个节点被删除后,图的连通分量数目增加(变为非连通),那么这个点就是关节点(割点)
    2. 如果某条边删除后,图的连通分量数目增加,那这条边就是桥
  • 算法(白书P312)

    • 定义dfn[i]:=dfs遍历时访问i点的次序
      ow[i]:=i点或i点后代能通过非父子边能到达的最早的祖先节点
    • 为割点的条件:
      1. i为树根,且有一个以上的子树
      2. i不是树根,且存在树边(i,son),low[son]>=dfn[i]
    • 为桥的条件
      树边(i,son), low[son]>dfn[i]

最长路径

任选一点x,求出离x最远的点s,再从s出发,找离s最远的点t,s-t即为最长路径

代码

GNU C++17 Accepted 561 ms 24600 KB

#include <bits/stdc++.h>
using namespace std;

const int maxn = 3e5 + 100;
int n, m;
struct edge
{
    int to, cost;
    edge(int to = 0, int cost = 0) {this->to = to; this->cost = cost;}
};
vector<edge> G[maxn];
set<pair<int, int>> Bridges;
int low[maxn], dfn[maxn];
int dfs_clock = 0;
void dfs(int cur, int fa)
{
    low[cur] = dfn[cur] = ++dfs_clock;
    for (auto &e : G[cur])
    {
        int son = e.to;
        if (!dfn[son])
        {
            dfs(son, cur);
            low[cur] = min(low[cur], low[son]);
            if (low[son] > dfn[cur]) Bridges.insert(pair<int, int>(max(cur, son), min(cur, son)));
        }
        else if(son != fa && dfn[son]<dfn[cur]) low[cur] = min(low[cur], dfn[son]);
    }
}

int Max = 0, MaxNode = 0;
int d[maxn];
void dfs1(int cur, int deep)
{
    d[cur] = deep;
    if (deep > Max) {Max = deep; MaxNode = cur;}
    for (auto &e : G[cur])
    {
        int son = e.to;
        if(d[son] == -1)
        {
            dfs1(son, deep+e.cost);
        }
    }
}


int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(edge(v, 1));
        G[v].push_back(edge(u, 1));
    }
    dfs(1, -1);
    for (int i = 1; i <= n; ++i)
    {
        for (auto &e : G[i])
        {
            if (!Bridges.count(pair<int, int>(max(i, e.to), min(i, e.to))) ) e.cost = 0;
        }
    }
    memset(d, -1, sizeof(d));
    dfs1(1, 0);
    memset(d, -1, sizeof(d));
    dfs1(MaxNode, 0);
    cout << Max << endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/litmxs/article/details/80968936