hdu 4612 Warm up 边双连通分量+树的直径

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
struct Edge
{
    int from,to,tag;
};

int n,m,dfn[200000+5],low[200000+5],vis[200000+5],dep,num,p[200000+5];
vector<Edge>edges;
vector<int>G[200000+5];
vector<int>g[200000+5];

void AddEdge(int from,int to)
{
    int i,flag=0;
    for(i=0; i<G[from].size(); i++)
        if(edges[G[from][i]].to==to)
        {
            edges[G[from][i]].tag++;
            flag=1;
            break;
        }
    if(!flag)
    {
        Edge tp;
        tp.from=from;
        tp.to=to;
        tp.tag=0;
        edges.push_back(tp);
        G[from].push_back(edges.size()-1);
    }
}

void dfs(int u,int fa)
{
    dfn[u]=low[u]=++dep;
    for(int i=0; i<G[u].size(); i++)
    {
        Edge t=edges[G[u][i]];
        if(!vis[t.to])
        {
            vis[t.to]=1;
            dfs(t.to,u);
            low[u]=min(low[u],low[t.to]);
            if(low[t.to]>dfn[u]&&!t.tag)
            {
                g[u].push_back(t.to);
                g[t.to].push_back(u);
                num++;
            }
        }
        else if(t.to!=fa||t.tag)
            low[u]=min(low[u],dfn[t.to]);
    }
}

void dfs2(int u,int bcc)
{
    p[u]=bcc;
    for(int i=0; i<G[u].size(); i++)
    {
        int to=edges[G[u][i]].to;
        bool f=true;
        for(int j=0;j<g[u].size();j++)
        {
            int v=g[u][j];
            if(v==to)
            {
                f=false;
                break;
            }
        }
        if(!f||vis[to]) continue;
        vis[to]=1;
        dfs2(to,bcc);
    }
}

void dfs3(int u,int dep)
{
    vis[u]=dep;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(vis[v]==-1)
            dfs3(v,dep+1);
    }
}

void find_bcc()
{
    int i,j,bcc,u,v;
    memset(vis,0,sizeof(vis));
    num=dep=0;
    for(i=1; i<=n; i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            dfs(i,-1);
        }
    }
    memset(vis,0,sizeof(vis));
    memset(p,0xff,sizeof(p));
    bcc=0;
    for(i=1; i<=n; i++)
    {
        if(!vis[i])
        {
            bcc++;
            vis[i]=1;
            dfs2(i,bcc);
        }
    }

    for(i=0;i<=n;i++)
        G[i].clear();

    for(i=1;i<=n;i++)
        for(j=0;j<g[i].size();j++)
    {
        int v=g[i][j];
        if(p[v]!=p[i])
        {
            G[p[i]].push_back(p[v]);
        }
    }
    memset(vis,0xff,sizeof(vis));
    dfs3(1,1);
    int flag,maxn=0;
    for(i=1;i<=bcc;i++)
    {
        if(vis[i]>=maxn)
        {
            flag=i;
            maxn=vis[i];
        }
    }
    memset(vis,0xff,sizeof(vis));
    dfs3(flag,0);
    maxn=0;
    for(i=1;i<=bcc;i++)
    {
        if(vis[i]>maxn)
            maxn=vis[i];
    }
    printf("%d\n",num-maxn);
}

int main()
{
    int _,i,u,v;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        edges.clear();
        for(i=0; i<=n; i++)
        {
            G[i].clear();
            g[i].clear();
        }
        for(i=1; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            AddEdge(u,v);
            AddEdge(v,u);
        }
        find_bcc();
    }
    return 0;
}

你可能感兴趣的:(hdu 4612 Warm up 边双连通分量+树的直径)