zoukankan      html  css  js  c++  java
  • hdu 4587 2013南京邀请赛B题/ / 求割点后连通分量数变形。

    题意:求一个无向图的,去掉两个不同的点后最多有几个连通分量。

     思路:枚举每个点,假设去掉该点,然后对图求割点后连通分量数,更新最大的即可。算法相对简单,但是注意几个细节:

    1:原图可能不连通。

    2:有的连通分量只有一个点,当舍去该点时候,连通分量-1;

    复习求割点的好题!



    #include<iostream>
    #include<cstdio>
    #include<vector>
    using namespace std;
    int n,m;
    vector<vector<int> >e(10010);
    int dfn[5010];int low[5010];int vis[5010];
    int times=0;
    int subset[5010];
    int root=0;
    int rf=0;
    int son=0;
    void tarjan(int u,int fa)     //无向图tarjan记录父亲  
    {
        if(u==rf)return;          //是被枚举的点,舍去(从图中删去)。
        dfn[u]=low[u]=times++;
        for(int i=0;i<e[u].size();i++)
        {
            int v=e[u][i];
            if(v==rf)continue;     // 这里注意,舍去的点不要了
            if(!vis[v])
            {
                vis[v]=1;
                tarjan(v,u);
                if(low[v]<low[u])low[u]=low[v];
                if(u==root)                   //求割点是根的情况
                  {
                      son++;
                  }
                else                  // 其他情况
                {
                    if(dfn[u]<=low[v])    //subset【u】+1记录 以u为割点后形成的连通分量数
                        subset[u]++;
                }
    
            }
            else if(v!=fa)         //条件注意
            {
                if(dfn[v]<low[u])low[u]=dfn[v];
            }
        }
        return ;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            for(int i=0;i<=n;i++)
               {
                 dfn[i]=low[i]=subset[i]=vis[i]=0;
                 e[i].clear();
               }
            int ta,tb;
          for(int i=0;i<m;i++)
          {
              scanf("%d%d",&ta,&tb);
               e[ta].push_back(tb);
               e[tb].push_back(ta);
          }
          int maxx=0;
          for(int i=0;i<n;i++)   //枚举每个点
          {
              rf=i;               //i舍去
              vis[rf]=1;
              int scc=0;
              int maxson=0;
              for(int iii=0;iii<n;iii++)          //考虑原图不连通!
                 {
                     if(!vis[iii])
                     {
                         vis[iii]=1;
                         root=iii;
                         tarjan(iii,-1);
                         scc++;                     //连通分量数
                         if(son>maxson)maxson=son;    //求出每个连通分量的根的最大的son
                         son=0;                         //每个连通分量要更新son
                     }
                 }
                if(e[i].size()==0)scc--;    // 注意点!!!:该连通分量只有一个点!舍去的话就没了。
              for(int ii=0;ii<n;ii++)             //取最大的
              {
                  if(scc+subset[ii]+1-1>maxx)maxx=scc+subset[ii]+1-1;
              }
              if(scc+maxson-1>maxx)maxx=maxson+scc-1;   
              for(int j=0;j<n;j++)    //不忘更新!
              {
                  dfn[j]=low[j]=subset[j]=vis[j]=0;
              }
              son=times=0;
          }
          cout<<maxx<<endl;
        }
        return 0;
    }
    


  • 相关阅读:
    [NOIP2002 提高组] 均分纸牌
    洛谷 P1303 A*B Problem
    OpenJudge 1.6.5 年龄与疾病
    hdu 3340 线段树思路活用
    poj 2464 线段树统计区间..两棵树
    hdu 4419 矩形面积覆盖颜色
    经典动态规划 dp Rqnoj 57
    最基础二维线段树 hdu 1823 (简单)
    hdu 3564 线段树+dp
    spoj 1557 线段树 区间最大连续和 (不重复数)
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925714.html
Copyright © 2011-2022 走看看