• 边双连通分量


    https://blog.csdn.net/a_forever_dream/article/details/103019013?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5

    找出所有的桥出来,然后去掉桥即可

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int MAXN=1e5,MAXM=1e6;
    struct Edge{
    	int from,to,nxt;
    }e[MAXM];
    int head[MAXN],edgeCnt=1;
    void addEdge(int u,int v)
    {
    	e[++edgeCnt].from=u;
    	e[edgeCnt].to=v;
    	e[edgeCnt].nxt=head[u];
    	head[u]=edgeCnt;
    }
    int dfn[MAXN],low[MAXN],dfnCnt=0;
    bool bridge[MAXM];
    void tarjan(int x,int in_edge)
    {
    	dfn[x]=low[x]=++dfnCnt;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int nowV=e[i].to;
    		if(!dfn[nowV])
    		{
    			tarjan(nowV,i);
    			if(low[nowV]>dfn[x])
    			{
    				bridge[i]=bridge[i^1]=1;
    			}
    			low[x]=min(low[x],low[nowV]);
    		}
    		else 
    		    if(i!=(in_edge^1))
    		     {
    			     low[x]=min(low[x],dfn[nowV]);
    		     }
    	}
    }
    int inDcc[MAXN];
    void dfs(int x,int nowDcc)
    {
    	inDcc[x]=nowDcc;//将X点归入nowdcc这个边双中 
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int nowV=e[i].to;
    		if(inDcc[nowV]||bridge[i])
    		//如果已归到某个边双,或第I条边是桥的话 
    		    continue;
    		dfs(nowV,nowDcc);
    	}
    }
    int main(){
    	int n,m;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int u,v;
    		scanf("%d%d",&u,&v);
    		addEdge(u,v);
    		addEdge(v,u);
    	}
    	for(int i=1;i<=n;i++) //找出所有的桥出来 
    		if(!dfn[i])
    		    tarjan(i,0);
    	int nowDcc=0;
    	for(int i=1;i<=n;i++) //如果i点还没有归到某个边双 
    		if(!inDcc[i])
    		   dfs(i,++nowDcc);
    	printf("%d
    ",nowDcc);
    	return 0;
    }
    

      

    做法1
    在请出Tarjan之前,我们先介绍另外一种做法:第一次 dfs找出割边,然后第二次 dfs 在不经过割边的情况下遍历所有点,每一次遍历经过的一个子图就是一个边双。

    做法2
    用类似找点双的做法,但是栈里面压点,不压边。

    int dfn[maxn],low[maxn],belong[maxn],id=0,cnt=0;
    int zhan[maxn],t=0;
    void dfs(int x,int from)
    {
    	dfn[x]=low[x]=++id;zhan[++t]=x;
    	for(int i=first[x];i;i=e[i].next)
    	{
    		if(i==(from^1))continue;
    		int y=e[i].y;
    		if(!dfn[y])
    		{
    			dfs(y,i);
    			if(low[y]<low[x])low[x]=low[y];
    		}
    		else if(dfn[y]<low[x])low[x]=dfn[y];
    	}
    	if(dfn[x]==low[x])
    	{
    		cnt++; int xx;
    		do{
    			xx=zhan[t--];
    			belong[xx]=cnt;
    		}while(xx!=x);
    	}
    }
    原文链接:https://blog.csdn.net/a_forever_dream/java/article/details/103019013
    

      

  • 相关阅读:
    专职DBA-MySQL体系结构与基本管理
    JSON
    MIME类型
    文件上传下载
    response常用的方法
    2020.11.27小记
    HTTP请求状态码
    1561. Maximum Number of Coins You Can Get
    1558. Minimum Numbers of Function Calls to Make Target Array
    1557. Minimum Number of Vertices to Reach All Nodes
  • 原文地址:https://www.cnblogs.com/cutemush/p/12681811.html
Copyright © 2020-2023  润新知