HDU 4635 Strongly connected

14:

    关键字 强联通

            题目求最多加多少条边使图不不再是一个强联通

我们逆向思维:

先假设n*(n-1)边 那么一定强联通 ,问最少减去多少条边 不再联通

那么只要枚举一个联通块就可以

因为其他边肯定与他有联系

CODE:

#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<stack>
using namespace std;

const int N=200010;
const int M=1000020;
struct node
{
    int v,next;
}e[M*2];

int head[N];
int dfn[N],low[N],dp[N][2];
int vis[M];
int n,m,cnt,ans;

void add(int u,int v)
{
    e[cnt].v=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}

void dfs(int u)
{
    dfn[u]=low[u]=cnt++;
    dp[u][0]=dp[u][1]=0;
    for (int i=head[u];i!=-1;i=e[i].next)
    {
        int j=e[i].v;
        if (!vis[i>>1])
        {
            vis[i>>1]=1;
            if (dfn[j]==0)
            {
                dfs(j);
                ans+=dfn[u]<low[j];
                int tmp=dp[j][0]+(dfn[u]<low[j]);
                if (tmp>dp[u][0]){
                dp[u][1]=dp[u][0],dp[u][0]=tmp;}
                else
                if (tmp>dp[u][1]) dp[u][1]=tmp;
                low[u]=min(low[u],low[j]);
            }
        else low[u]=min(low[u],dfn[j]);
    }
   }
}
int main()
{
    while (scanf("%d%d",&n,&m))
    {
        if (n==0&&m==0) break;
        cnt=ans=0;
        memset(head,-1,sizeof(head));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        while (m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        cnt=1;
        memset(vis,0,sizeof(vis));
        dfs(1);
        int tmp=0;
        for (int i=1;i<=n;i++)
        tmp=max(tmp,dp[i][0]+dp[i][1]);
        printf("%d\n",ans-tmp);
    }
    return 0;
}

  

posted on 2015-02-18 01:55  forgot93  阅读(122)  评论(0编辑  收藏  举报

导航