E. We Need More Bosses

原题链接

题解

1.已知如果两个点之间有两条边不重合的路径,那么这两个点就在一个边强连通分量里,所以我们可以把处于同一个边强连通分量的点缩起来
在这里,我忘记了怎么求边强连通分量,所以我再提醒一下自己
已知树结构是不存在强连通分量的,它的特性是深度大的节点只有一条回到深度小的节点的边,所以我们深度搜索,对遇到的节点进行深搜顺序标记,记录每个节点能去的深序最小节点
假如遍历到当前节点 u,已知其子节点能去的最小的深序节点比它还小,那说明它不是这个边强连通分量的深序最小点;
如果其子节点的最小深序节点等于它,那么代表它是这个边强连通分量的深序最小点

2.把边强连通分量缩点之后,由于保证联通的无向图,所以剩余节点一定是树
树中求两点最大距离等价于求树的直径,在这里我又忘记怎么求了,所以我再提醒一下自己
求树的直径:双dfs法,两次搜索深度最大的点
这里我证明为什么随便找一个点然后深搜深度最大的点一定是直径的端点
反证法:

code

// LUOGU_RID: 159070334
#include<bits/stdc++.h>
using namespace std;
int vis[300005]={0},lst[300005]={0};
int cnt=0;
stack<int> st;
vector<int> G[300005];
int belong[300005];
int tot=0;
void dfs(int now,int fa)
{
    vis[now]=++cnt;
    lst[now]=cnt;
    st.push(now);
    for(auto next:G[now])
    {
        if(next==fa) continue;
        if(vis[next]) lst[now]=min(vis[next],lst[now]);
        else
        {
            dfs(next,now);
            lst[now]=min(lst[now],lst[next]);
        }
    }
    if(vis[now]==lst[now])
    {
        int x;
        tot++;
        do
        {
            x=st.top();
            st.pop();
            belong[x]=tot;
        }while(x!=now);
    }
}


vector<int> E[300005];
int depth[300006]={0};
int root,maxd=-1;
void dfs1(int now,int fa)
{
    if(depth[now]>maxd)
    {
        maxd=depth[now];
        root=now;
    }
    for(auto next:E[now])
    {
        if(next==fa||depth[next]) continue;
        depth[next]=depth[now]+1;
        dfs1(next,now);
    }
}

int dfs2(int now,int fa)
{
    int ans=depth[now];
    for(auto next:E[now])
    {
        if(next==fa||depth[next]) continue;//由于建边的时候重复建边了
        depth[next]=depth[now]+1;
        ans=max(ans,dfs2(next,now));
    }
    return ans;
}
int main()
{

        int n,m;
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            int x,y;
            cin>>x>>y;
            G[x].push_back(y);
            G[y].push_back(x);
        }

        dfs(1,1);

        for(int i=1;i<=n;i++)
        {
            for(auto next:G[i])
            {
                if(belong[next]!=belong[i])
                {
                    E[belong[i]].push_back(belong[next]);
                    E[belong[next]].push_back(belong[i]);
                }
            }
        }


        dfs1(1,-1);
        memset(depth,0,sizeof depth);
        cout<<dfs2(root,-1);
    return 0;
}

posted @   纯粹的  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示