hdu 4612 (双联通+树形DP)

加一条边后最少还有多少个桥,先Tarjan双联通缩点,

然后建树,求出树的直径,在直径起点终点加一条边去的桥最多,





 

#pragma comment(linker, "/STACK:1024000000,1024000000")

#include<stdio.h>

#include<string.h>

#include<stack>

#define N 200001

using namespace std;

int belong[N],head[N],num,ins[N],n,dfs[N],low[N],idx,ans,num1;

struct edge

{

    int st,ed,next;

}E[N*10],e[N*10];

void addedge(int x,int y)

{

    E[num].st=x;

    E[num].ed=y;

    E[num].next=head[x];

    head[x]=num++;

}

void Addedge(int x,int y)

{

    e[num1].st=x;

    e[num1].ed=y;

    e[num1].next=head[x];

    head[x]=num1++;

}

stack<int>Q;

void Tarjan(int u,int father)

{

   int i,j,v,flag=0;

    low[u]=dfs[u]=idx++;

    Q.push(u);

    for(i=head[u];i!=-1;i=E[i].next)

    {

        j=E[i].ed;

        if(dfs[j]==-1)

        {

            Tarjan(j,u);

            low[u]=low[u]>low[j]?low[j]:low[u];

        }

        else if(j==father)

        {

            if(flag)

                low[u]=low[u]>dfs[j]?dfs[j]:low[u];

            flag++;

            

        }

        else low[u]=low[u]>dfs[j]?dfs[j]:low[u];

        

    }

    if(dfs[u]==low[u])

    {

        do

        {

            v=Q.top();

            Q.pop();

            belong[v]=ans;

        }while(v!=u);

        ans++;

    }

}

void read()

{

    memset(head,-1,sizeof(head));

    num1=0;

    for(int i=0;i<num;i+=2)

    {

        int x=belong[E[i].st];

        int y=belong[E[i].ed];

        if(x==y)continue;

        Addedge(x,y);

        Addedge(y,x);

    }

}

int dis;

int dist(int u)

{

    ins[u]=1;

    int max=0,mmax=0;

    for(int i=head[u];i!=-1;i=e[i].next)

    {

        int v=e[i].ed;

        if(ins[v]==1)continue;

        int temp=dist(v);

        if(temp>mmax)

        {

            max=mmax;

            mmax=temp;            

        }

        else if(temp>max)

        {

            max=temp;

        }

    }

    if(dis<(mmax+max+1))

        dis=mmax+max+1;

    return mmax+1;

}

int main()

{

    int i,m,x,y;

    while(scanf("%d%d",&n,&m),n||m)

    {

        memset(head,-1,sizeof(head));

        num=0;

        for(i=0;i<m;i++)

        {

            scanf("%d%d",&x,&y);

            addedge(x,y);

            addedge(y,x);

        }

        memset(dfs,-1,sizeof(dfs));

        memset(low,-1,sizeof(low));

        memset(ins,0,sizeof(ins));

        idx=ans=0;

        Tarjan(1,-1);

        read();

        memset(ins,0,sizeof(ins));

        dis=0;

        dist(1);

        printf("%d\n",ans-dis);

    }

    return 0;

}


 

 

你可能感兴趣的:(HDU)