HDU 4612 Warm up

给出一个无向图,你可以加一条边,使得加上边之后的图割边数量最少。

方法:每个边双连通分量缩点,形成一个树,树上的每条边都是割边,割边数量为S1;

接下来只要算出树上最长路径(树的直径)就可以了,最长路径两段连线,路径上的割边都不可能再成为割边了,记最长路径长度为S2;

Ans=S1-S2;

第一步可以用Tarjan算法

树的直径可以这样求:先随便找一个点P,DFS一下,找到与P距离最远的那个点St;然后从St出发,再进行一次DFS,与St相距最远的那个点的距离就是树的直径。

 

 

这个题目搞了一天,一直是MLE,后来把vector改成数组就AC了.....

 

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn=200000+10;
const int Maxn=2*1000000+10;
const int INF=0x7FFFFFFF;
int low[maxn];
int dfn[maxn];
int U[Maxn],V[Maxn];
int flag[Maxn];
int head[maxn];

struct Edge
{
    int to,ans;
    int next;
} edge[Maxn];

int N,M;
int tmpdfn;
int tot;
int son;
int Start,End;
int TxT[maxn];
int ShuYu[maxn];
int SS,Ans,JiLu,MA,St;
vector<int>Tree[maxn];
int Biao[maxn];

void init()
{

    for(int i=0; i<=N; i++) Tree[i].clear();

    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(flag,0,sizeof(flag));
    memset(TxT,0,sizeof(TxT));
    memset(ShuYu,0,sizeof ShuYu);
    memset(Biao,0,sizeof Biao);
    memset(head,-1,sizeof head);
    low[1]=dfn[1]=1;
    tmpdfn=0;
    tot=0;
    son=0;
    SS=0;
}

void AddEdge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    edge[tot].ans=0;
    head[u]=tot++;

    edge[tot].to=u;
    edge[tot].next=head[v];
    edge[tot].ans=0;
    head[v]=tot++;
}

int Tarjan(int u,int id)
{
    tmpdfn++;
    int lowu=dfn[u]=tmpdfn;
    for(int i = head[u]; i != -1; i = edge[i].next)
    {
        int B=i;
        if(!dfn[edge[B].to])
        {
            int lowv=Tarjan(edge[B].to,B);
            lowu=min(lowu,lowv);
            if(lowv>=dfn[u])
            {
                if(u==1) son++;
                if(lowv>dfn[u])
                {
                    edge[B].ans=1;
                    edge[B^1].ans=1;
                }
            }
        }
        else if(dfn[edge[B].to])
        {
            if(B/2==id/2) continue;
            lowu=min(lowu,dfn[edge[B].to]);
        }
    }
    low[u]=lowu;
    return lowu;
}

void Dfs(int x,int y)
{
    int XZ=0;
    for(int i = head[x]; i != -1; i = edge[i].next)
    {
        int B=i;
        if(!flag[B/2]&&!TxT[edge[B].to])
        {
            XZ=1;
            flag[B/2]=1;
            TxT[edge[B].to]=1;
            ShuYu[x]=SS;
            ShuYu[edge[B].to]=SS;
            Dfs(edge[B].to,y+1);
        }
    }
    if(!XZ&&!y) ShuYu[x]=SS;
}

void Slove()
{
    for(int i=0; i<2*M; i++)
        if(edge[i].ans)
            flag[i/2]=1;

    for(int i=Start; i<=End; i++)
    {
        if(!TxT[i])
        {
            TxT[i]=1;
            SS++;
            Dfs(i,0);
        }
    }
}

void dfs1(int now,int len)
{
    if(len>MA)
    {
        MA=len;
        St=now;
    }
    Biao[now]=1;
    for(int i=0; i<Tree[now].size(); i++)
        if(Biao[Tree[now][i]]==0)
            dfs1(Tree[now][i],len+1);
}

void dfs2(int now,int len)
{
    if(len>MA) MA=len;
    Biao[now]=1;
    for(int i=0; i<Tree[now].size(); i++)
        if(Biao[Tree[now][i]]==0)
            dfs2(Tree[now][i],len+1);
}

int main()
{
    while(~scanf("%d%d",&N,&M))
    {
        if(N==0&&M==0) break;
        init();
        for(int i=0; i<M; i++)
        {
            scanf("%d%d",&U[i],&V[i]);
            AddEdge(U[i],V[i]);
        }

        Start=1;
        End=N;
        Tarjan(1,-1);
        Slove();
        for(int i=0; i<M; i++)
        {
            if(ShuYu[U[i]]==ShuYu[V[i]]) continue;
            Tree[ShuYu[U[i]]].push_back(ShuYu[V[i]]);
            Tree[ShuYu[V[i]]].push_back(ShuYu[U[i]]);
        }
        MA=-INF;
        dfs1(1,0);
        memset(Biao,0,sizeof Biao);
        MA=-INF;
        dfs2(St,0);
        Ans=MA;

        printf("%d\n",SS-1-Ans);
    }
    return 0;
}

 

posted @ 2015-08-27 21:59  Fighting_Heart  阅读(328)  评论(0编辑  收藏  举报