无向图的割点和桥

无向图的割点和桥

1.割点

# include <bits/stdc++.h>
using namespace std;

const int MAXN=2e4+100;
vector<int> G[MAXN];
int dfn[MAXN],iscut[MAXN],low[MAXN]; //iscut[i]表示i是割点
int dfs_clock=0;
void init()
{
   dfs_clock=0;
   for(int i=1;i<MAXN;++i) G[i].clear();
   memset(iscut,0,sizeof(iscut));
   memset(low,0,sizeof(low));
   memset(dfn,0,sizeof(dfn));
}
int dfs(int u,int fa)
{
   int lowu; lowu=dfn[u]=++dfs_clock;
   int child=0;
   int len=G[u].size();
   for(int i=0;i<len;++i){
       int v=G[u][i];
       if(!dfn[v]){
           child++;
           int lowv=dfs(v,u);
           lowu=min(lowu,lowv);
           if(lowv>=dfn[u]){ //如果求桥,去掉等号
               iscut[u]++;
          }
      }else if(dfn[v]<dfn[u]&&v!=fa){
           lowu=min(lowu,dfn[v]);
      }
  }
   if(fa<0&&child==1) iscut[u]=0;
   else if(fa<0&&child>=2) iscut[u]=child-1;
   return low[u]=lowu;
}
int main()
{
   init();
   int n,m; scanf("%d%d",&n,&m);
   while(m--){
       int u,v; scanf("%d%d",&u,&v);
       G[u].push_back(v);
       G[v].push_back(u);
  }
   for(int i=1;i<=n;++i){
       if(!dfn[i]) dfs(i,-1);
  }//不连通
   //dfs(1,-1);
   int ans=0;
   for(int i=1;i<=n;++i){
       if(iscut[i]) ans++;
  }
   printf("%d\n",ans);
   for(int i=1;i<=n;++i){
       if(iscut[i]) printf("%d ",i);
  }
   return 0;
}
//u->v  该边导致u成为割点
//当dfn[u]==low[v]时u->v为返祖边,u、v处于同一双连通分量中
//当dfn[u]<low[v]时u->v为割边
//删除割点u产生的连通数目为:u所在的连通分量数目+与u所连接的割边的数目+1(边:fa->u)
# include <bits/stdc++.h>
using namespace std;

const int MAXN=1e3+100;
int dfn[MAXN],iscut[MAXN],low[MAXN];
int dfs_clock=0;
vector<int> G[MAXN];
void init()
{
   dfs_clock=0;
   for(int i=1;i<MAXN;++i) G[i].clear();
   memset(iscut,0,sizeof(iscut));
   memset(low,0,sizeof(low));
   memset(dfn,0,sizeof(dfn));
}
int dfs(int u,int fa)
{
   int lowu; lowu=dfn[u]=++dfs_clock;
   int child=0;
   int len=G[u].size();
   for(int i=0;i<len;++i){
       int v=G[u][i];
       if(!dfn[v]){
           child++;
           int lowv=dfs(v,u);
           lowu=min(lowu,lowv);
           if(lowv>=dfn[u]){
               iscut[u]++;
          }
      }else if(dfn[v]<dfn[u]&&v!=fa){
           lowu=min(lowu,dfn[v]);
      }
  }
   if(fa<0&&child==1) iscut[u]=0;
   else if(fa<0&&child>=2) iscut[u]=child-1;
   return low[u]=lowu;
}
int main()
{
   int kase=0;
   while(1){
       init();
       int u,v,t=0;
       while(scanf("%d",&u)==1&&u!=0){
           t++;
           scanf("%d",&v);
           G[u].push_back(v); G[v].push_back(u);
      }
       if(t==0) break;
       dfs(1,-1);
       int num=0;
       for(int i=1;i<=1000;++i){
           if(iscut[i]) num++;
      }
       printf("Network #%d\n",++kase);
       if(num>0){
           for(int i=1;i<=1000;++i){
               if(iscut[i]){
                   printf(" SPF node %d leaves %d subnets\n",i,iscut[i]+1);
              }
          }
      }else printf(" No SPF nodes\n");
       if(kase) puts("");
  }

   return 0;
}

2.桥

//HDU 3849 By Recognizing 求无向图的桥数目
# include <bits/stdc++.h>
using namespace std;

const int MAXN=1e4+100;
const int MAXM=1e5+100;
vector<int> G[MAXN];
int dfn[MAXN],low[MAXN];
int dfs_clock=0,n,m;
void init()
{
   dfs_clock=0;
   for(int i=1;i<=n;++i) G[i].clear();
   memset(low,0,sizeof(low));
   memset(dfn,0,sizeof(dfn));
}
void dfs(int u,int fa)
{
   low[u]=dfn[u]=++dfs_clock;
   int len=G[u].size();
   for(int i=0;i<len;++i){
       int v=G[u][i];
       if(v==fa) continue;
       if(!dfn[v]){
           dfs(v,u);
           low[u]=min(low[u],low[v]);
      }else{
           low[u]=min(low[u],dfn[v]);
      }
  }
}
struct node{
   char s[20];
   bool operator < (const node& rhs)const
  {
       return strcmp(s,rhs.s)<0;
  }
};
map<node,int> mp;
struct Edge{
   node u,v;
   int flag;
}edge[MAXM];
int main()
{
   int T; scanf("%d",&T);
   int id,x,y,fflag=0,ans;
   while(T--){
       init();
       mp.clear();
       id=0; fflag=0; ans=0;
       scanf("%d%d",&n,&m);
       for(int i=1;i<=m;++i){
           edge[i].flag=0;
           scanf("%s%s",edge[i].u.s,edge[i].v.s);
           if(mp.find(edge[i].u)==mp.end()) mp[edge[i].u]=++id;
           if(mp.find(edge[i].v)==mp.end()) mp[edge[i].v]=++id;
           x=mp[edge[i].u],y=mp[edge[i].v];
           G[x].push_back(y); G[y].push_back(x);
      }
       dfs(1,-1);
       for(int i=1;i<=n;++i){
           if(!dfn[i]){
               fflag=1;
               break;
          }
      }
       if(fflag){
           printf("0\n");
           continue;
      }

       for(int i=1;i<=m;++i){
           x=mp[edge[i].u],y=mp[edge[i].v];
           if(low[x]>dfn[y]||low[y]>dfn[x]) edge[i].flag=1,ans++;
      }
       printf("%d\n",ans);
       for(int i=1;i<=m;++i){
           if(edge[i].flag){
               printf("%s %s\n",edge[i].u.s,edge[i].v.s);
          }
      }
  }

   return 0;
}
/*
1
4 4
saerdna aswmtjdsj
aswmtjdsj mabodx
mabodx biribiri
aswmtjdsj biribiri
*/



posted @ 2022-02-27 13:40  fengzlj  阅读(57)  评论(0)    收藏  举报