hdu 4612 Warm up

http://acm.hdu.edu.cn/showproblem.php?pid=4612

将原图进行缩点 变成一个树

树上每条边都是一个桥 然后加一条边要加在树的直径两端才最优

代码:

#include<iostream>

#include<cstdio>

#include<string>

#include<cstring>

#include<cmath>

#include<set>

#include<map>

#include<stack>

#include<vector>

#include<algorithm>

#include<queue>

#include<bitset>

#include<deque>

#include<numeric>



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



using namespace std;





typedef long long ll;

typedef unsigned int uint;

typedef pair<int,int> pp;

const double eps=1e-9;

const int INF=0x3f3f3f3f;

const ll MOD=1000000007;

const int N=210000;

const int M=2100000;

int head1[N],I1;

int head2[N],I2;

struct node

{

    int j,next;

}edge1[M],edge2[M];

bool ev[M];

int dist[N];

int low[N],dfn[N],f[N],deep;

bool in[N],visited[N];

int num[N],sel[N];

stack<int>st;

queue<int>qt;

vector<int>vt[N];

void add1(int i,int j)

{

    edge1[I1].j=j;

    edge1[I1].next=head1[i];

    head1[i]=I1++;

}

void add2(int i,int j)

{

    edge2[I2].j=j;

    edge2[I2].next=head2[i];

    head2[i]=I2++;

}

void tarjan(int x)//将环缩点

{

    visited[x]=true;

    in[x]=true;

    st.push(x);

    low[x]=dfn[x]=deep++;

    for(int t=head1[x];t!=-1;t=edge1[t].next)

    if(!ev[t])

    {

        ev[t]=true;

        ev[t^1]=true;

        int j=edge1[t].j;

        if(visited[j]==false)

        {

            tarjan(j);

            low[x]=min(low[x],low[j]);



        }else if(in[j]==true)

        {

            low[x]=min(low[x],dfn[j]);

        }

    }

    if(low[x]==dfn[x])

    {

        while(st.top()!=x)

        {

            int k=st.top(); st.pop();

            in[k]=false;

            f[k]=x;

            vt[x].push_back(k);

        }

        int k=st.top(); st.pop();

        in[k]=false;

        f[k]=x;

    }

}

void buildNewGraph(int k)

{

    memset(head2,-1,sizeof(head2));I2=0;

    for(int i=0;i<k;++i)

    {

        for(int t=head1[i];t!=-1;t=edge1[t].next)

        {

            int j=edge1[t].j;

            if(f[i]!=f[j])

            {

                add2(f[j],f[i]);

                ++num[f[i]];

            }

        }

    }

}

void init(int n,int m)

{

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

    I1=0;

    while(m--)

    {

        int l,r;

        scanf("%d %d",&l,&r);

        --l;--r;

        add1(l,r);

        add1(r,l);

    }

}

int bfs(int x1,int n)

{

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

    queue<int>qt;

    dist[x1]=0;

    qt.push(x1);

    while(!qt.empty())

    {

        int x=qt.front();

        qt.pop();

        for(int t=head2[x];t!=-1;t=edge2[t].next)

        {

            int j=edge2[t].j;

            if(dist[j]==-1)

            {

                dist[j]=dist[x]+1;

                qt.push(j);

            }

        }

    }

    int k=0;

    for(int i=0;i<n;++i)

    if(dist[i]>dist[k])

    k=i;

    return k;

}

int solve(int n)

{

    int s=0,sum=0;

    for(int i=0;i<n;++i)

    if(f[i]==i)

    {s=i;++sum;}

    int k=bfs(s,n);

    k=bfs(k,n);

    return (sum-1-dist[k]);

}

int main()

{

    //freopen("data.in","r",stdin);

    int n,m;

    while(scanf("%d %d",&n,&m)!=EOF)

    {

        if(n==0&&m==0)

        break;

        init(n,m);

        while(!st.empty()) st.pop();

        for(int i=0;i<n;++i)

        {vt[i].clear();f[i]=i;}

        memset(in,false,sizeof(in));

        memset(visited,false,sizeof(visited));

        memset(ev,false,sizeof(ev));

        deep=0;

        for(int i=0;i<n;++i)

        if(!visited[i])

        tarjan(i);

        buildNewGraph(n);

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

    }

    return 0;

}

 

 

你可能感兴趣的:(HDU)