CodeForces 51 F.Caterpillar (edge biconnected component + tree diameter)

Description

A caterpillar graph is defined as an undirected acyclic (but can have self-loop) graph without multiple edges (but self-loops can have multiple edges), which is a tree without considering the diameter, and the non-diameter point of the tree is equal to the diameter of the distance can only be 1 . now give a n points m An undirected graph with edges, each operation can take two different points a , b merge into one point c , and all edges a d and b d both become c d , it can be seen that one step of operation will make the number of points minus one side of the graph unchanged, and the minimum number of operations to make the graph become a caterpillar graph

Input

Two integers in the first line n , m Indicates the number of points and edges, after m Enter two integers per line u , v represents an undirected edge

( 1 n 2000 , 0 m 10 5 )

Output

Output the minimum number of operands that make this graph a caterpillar graph

Sample Input

4 4
1 2
2 3
3 4
4 2

Sample Output

2

Solution

First, an edge biconnected component must be shrunk into a point. After shrinking the point, a forest is obtained. It is only necessary to consider each tree separately, and then connect each tree according to its diameter. For a tree, now it is necessary to make all non- The distance from the diameter point to the diameter is 1 , assuming that the number of points in the tree is x , the number of points on the diameter is and , the leaf point is with , then we only need to shrink the points that are not diameter points and non-leaf nodes. This part of the points is x and with + 2 , because there are two leaf nodes on the diameter, notice that if x = 1 There is only one leaf node on the diameter

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
#define maxn 2005
#define maxm 200005 
struct Edge
{
    int to,next;
    bool flag;//标记是否是桥
}edge[maxm];
int head[maxn],tot;
int low[maxn],dfn[maxn],stack[maxn],belong[maxn];//belong数组的值是1~block
int index,top;
int block;//边双连通块数
bool instack[maxn];
int bridge;//桥的数目
void addedge(int u,int v)
{
    edge[tot].to=v,edge[tot].next=head[u],edge[tot].flag=0;
    head[u]=tot++;
}
void Tarjan(int u,int pre)
{   
    int v;
    low[u]=dfn[u]=++index;
    stack[top++]=u;
    instack[u]=1;
    for(int i=head[u];~i;i=edge[i].next)
    {
        v=edge[i].to;
        if(v==pre)continue;
        if(!dfn[v])
        {
            Tarjan(v,u);
            if(low[u]>low[v])low[u]=low[v];
            if(low[v]>dfn[u])
            {
                bridge++;
                edge[i].flag=1;
                edge[i^1].flag=1;
            }
        }
        else if(instack[v]&&low[u]>dfn[v])
            low[u]=dfn[v];
    }
    if(low[u]==dfn[u])
    {
        block++;
        do
        {
            v=stack[--top];
            instack[v]=0;
            belong[v]=block;
        }
        while(v!=u);
     }
}
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}
int n,m,e[maxm][2],vis[maxn],mx,tar,res;
void dfs(int u,int fa,int dep)
{
    vis[u]=1;
    if(dep>mx)mx=dep,tar=u;
    int num=0;
    for(int i=head[u];~i;i=edge[i].next)
    {
        num++;
        int v=edge[i].to;
        if(v==fa)continue;
        dfs(v,u,dep+1);
    }
    if(num<=1)res++;
}
int main()
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&e[i][0],&e[i][1]);
        addedge(e[i][0],e[i][1]),addedge(e[i][1],e[i][0]);
    }
    memset(dfn,0,sizeof(dfn));
    memset(instack,0,sizeof(instack));
    index=top=block=0;
    for(int i=1;i<=n;i++)
        if(!dfn[i])Tarjan(i,0);
    init();
    for(int i=1;i<=m;i++)
    {
        int u=belong[e[i][0]],v=belong[e[i][1]];
        if(u!=v)addedge(u,v),addedge(v,u);
    }
    int ans=n;
    n=block;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
        if(!vis[i])
        {
            ans++;
            mx=0,tar=i,res=0;
            dfs(i,i,1);
            mx=0,res=0;
            dfs(tar,tar,1);
            if(mx>1)ans=ans-res+2-mx;
            else ans=ans-res+1-mx;//single point
        }
    ans--;
    printf("%d\n",ans);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324608019&siteId=291194637