CodeForces - 1000E We Need More Bosses(无向图缩点 + 树的直径)

版权声明:Why is everything so heavy? https://blog.csdn.net/lzc504603913/article/details/83213341

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

题意:求一个图,确定两点后,桥最多的数量。

解题思路:缩点后求树的直径即可。

这里保存无向图缩点代码,另外给出有向图的缩点代码

有向图缩点:https://blog.csdn.net/lzc504603913/article/details/79174951

#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <memory.h>
#include <bitset>
#include <map>
#include <deque>
#include <math.h>
#include <stdio.h>
using namespace std;

typedef long long int ll;

const int MAXN = 300005;
inline void scan_d(int &ret)
{
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9')
        ;
    while (c >= '0' && c <= '9')
    {
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}

vector<int> G[MAXN];
int N, M;
int color[MAXN];
int dfn[MAXN];
int low[MAXN];
int instack[MAXN];
int sta[MAXN];
int cnt = 0;
int vistime = 1;
int col = 1;

//树的直径部分

int dis[MAXN];
vector<int> childs[MAXN];
int vis[MAXN];
void dfs(int x)
{
    vis[x]=1;
    for (int i = 0; i < childs[x].size(); i++)
    {
        int ch = childs[x][i];
        if (vis[ch])
            continue;
        if (!dis[ch])
        {
            dis[ch] = dis[x] + 1;
            dfs(ch);
        }
    }
}

int longestpath()
{
    memset(dis, 0, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dfs(1);
    int j = 1;
    for (int i = 1; i < col; i++)
        if (dis[i] > dis[j])
            j = i;
    memset(dis, 0, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dfs(j);
    j = 1;
    for (int i = 1; i < col; i++)
        if (dis[i] > dis[j])
            j = i;
    return dis[j];
}

void init()
{

    for (int i = 0; i <= N; i++)
        G[i].clear();
    memset(color, 0, sizeof(color));
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(instack, 0, sizeof(instack));
    memset(sta, 0, sizeof(sta));
    for (int i = 0; i <= N; i++)
        childs[i].clear();

    cnt = 0;
    vistime = 1;
    col = 1;
}

void tarjan(int v1, int fa)
{
    dfn[v1] = low[v1] = vistime;
    vistime++;

    sta[cnt++] = v1;
    instack[v1] = 1;

    int flag = 0; //因为有重边,所以要记录往回走了多少次。
    for (int i = 0; i < G[v1].size(); i++)
    {
        if (G[v1][i] == fa && !flag)
        {
            flag = 1;
            continue;
        }

        if (!dfn[G[v1][i]])
        {
            tarjan(G[v1][i], v1);
            low[v1] = min(low[v1], low[G[v1][i]]);
        }
        else if (instack[G[v1][i]])
            low[v1] = min(low[v1], dfn[G[v1][i]]);
    }
    if (dfn[v1] == low[v1])
    {
        int temp;
        do
        {
            temp = sta[--cnt];
            color[temp] = col; //缩点
            instack[temp] = 0;

        } while (temp != v1);
        col++;
    }
}

void SD()
{
    for (int i = 1; i <= N; i++)
    {
        for (int j = 0; j < G[i].size(); j++)
        {
            if (color[i] != color[G[i][j]])
            {
                childs[color[i]].push_back(color[G[i][j]]);
                childs[color[G[i][j]]].push_back(color[i]);
            }
        }
    }
}

int main()
{

    scan_d(N);
    scan_d(M);

    init();
    for (int i = 1; i <= M; i++)
    {
        int a, b;
        scan_d(a);
        scan_d(b);
        G[a].push_back(b);
        G[b].push_back(a);
    }

    for (int i = 1; i <= N; i++)
        if (!dfn[i])
            tarjan(i, -1);
    SD();

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

    return 0;
}

猜你喜欢

转载自blog.csdn.net/lzc504603913/article/details/83213341