codeforces1000E. We Need More Bosses(无向图缩点+直径)

                                      E. We Need More Bosses

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Your friend is developing a computer game. He has already decided how the game world should look like — it should consist of nn locations connected by mm two-way passages. The passages are designed in such a way that it should be possible to get from any location to any other location.

Of course, some passages should be guarded by the monsters (if you just can go everywhere without any difficulties, then it's not fun, right?). Some crucial passages will be guarded by really fearsome monsters, requiring the hero to prepare for battle and designing his own tactics of defeating them (commonly these kinds of monsters are called bosses). And your friend wants you to help him place these bosses.

The game will start in location ss and end in location tt, but these locations are not chosen yet. After choosing these locations, your friend will place a boss in each passage such that it is impossible to get from ss to tt without using this passage. Your friend wants to place as much bosses as possible (because more challenges means more fun, right?), so he asks you to help him determine the maximum possible number of bosses, considering that any location can be chosen as ss or as tt.

Input

The first line contains two integers nn and mm (2≤n≤3⋅1052≤n≤3⋅105, n−1≤m≤3⋅105n−1≤m≤3⋅105) — the number of locations and passages, respectively.

Then mm lines follow, each containing two integers xx and yy (1≤x,y≤n1≤x,y≤n, x≠yx≠y) describing the endpoints of one of the passages.

It is guaranteed that there is no pair of locations directly connected by two or more passages, and that any location is reachable from any other location.

Output

Print one integer — the maximum number of bosses your friend can place, considering all possible choices for ss and tt.

Examples

input

Copy

5 5
1 2
2 3
3 1
4 1
5 2

output

Copy

2

input

Copy

4 3
1 2
4 3
3 2

output

Copy

3

 

一、原题地址

点我传送

 

二、大致题意

给出一张连通的图,现在对于选出的两个点S,T 保证在这两点之间的所有必经的路上都安置一个怪兽。

现在询问的是 :任意在图上选择两个点都能保证上述条件,那么所需的最少怪物是多少?

 

三、大致思路

首先对于一张图来说,必经的那些路就是‘桥’,所以我们需要处理出桥。

无向图的tarjan缩点套上,然后原图就变成了一棵树,对于一棵树来讲任意的边都是桥了,那么问题就转化为了求树上两点之间最大的桥数了。显然就是树的直径。跑两次DFS就能得到答案了。

 

四、代码

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#include<iostream>
#include<deque>
#include<map>
#include<stack>
#include<set>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;


const int maxn=3e5+5;
int head[maxn];
int dfn[maxn],low[maxn];
int scc[maxn],scc_cnt;
int stck[maxn],stck_top;
int times;
int tot;
struct Edge
{
    int v,next;
}e[maxn<<1];

void add(int u,int v)
{
    e[tot].next=head[u];
    e[tot].v=v;
    head[u]=tot++;
}


int n,m,T;
void init()
{
    scc_cnt=tot=times=stck_top=0;
    for(int i=1;i<=n;i++)
    {
        dfn[i]=low[i]=0;
        head[i]=-1;
    }
}

void tarjan(int u,int fa)
{
    dfn[u]=low[u]=++times;
    stck[++stck_top]=u;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        int To=e[i].v;
        if(To==fa) continue;
        if(!dfn[To]) {
              tarjan(To,u);
              low[u]=min(low[u],low[To]);
        }
        else low[u]=min(low[u],dfn[To]);
    }
    if(low[u]==dfn[u]){
        scc_cnt++;
        while(true){
            int x=stck[stck_top--];
            scc[x]=scc_cnt;
            if(x==u) break;
        }
    }
}


vector<int>Edge[maxn];
int ans;
int tail;
void dfs(int nx,int pre,int step)
{
    if(ans<=step)
    {
        tail=nx;
        ans=step;
    }
    for(int i=0;i<Edge[nx].size();i++)
    {
        int to =Edge[nx][i];
        if(to!=pre)dfs(to,nx,step+1);
    }
    return ;
}

int work()
{
    ans=0;
    dfs(1,-1,0);
    dfs(tail,-1,0);
    return ans;
}

int main()
{
    scanf("%d %d",&n,&m);
    init();
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])tarjan(i,-1);
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=head[i];j!=-1;j=e[j].next)
        {
            int to =e[j].v;
            if(scc[i]!=scc[to])
            {
                Edge[ scc[i]].push_back(scc[to]);
            }
        }
    }
    //printf("Finish\n");

    printf("%d\n",work());

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值