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;
    }
    


  • 相关阅读:
    课堂作业04 2017.10.27
    课程作业 03 动手动脑 2017.10.20
    课程作业 03 2017.10.20
    HDU 3974 Assign the task
    POJ 2155 Matrix
    POJ 2481 Cows
    HDU 3038 How Many Answers Are Wrong
    CS Academy Array Removal
    POJ_1330 Nearest Common Ancestors LCA
    CF Round 427 D. Palindromic characteristics
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925714.html
Copyright © 2011-2022 走看看