• 无向图的桥


    https://www.luogu.com.cn/problem/P1656
    题意:给一张联通的无向图,问是否存在边,去掉它就不是全联通了,输出边的端点

    input

    6 6
    1 2
    2 3
    2 4
    3 5
    4 5
    5 6
    

    output

    1 2
    5 6
    

    思路:

    用tarjan处理出每个点的low和dfn,对于一条边(u->j),如果low[j] > dfn[u],表明j点除了通过u点(父亲),无法到达u及以前的点,把它去掉就行了.
    但是因为是无向图,所以需要用sign[i]表示i边是否走过,有个技巧是,一条无向边的去和来,对应的是i和i^1.

    代码

    /*
    belong[i]表示i在第几个连通分量里
    dfn[i]表示i点在搜索时的时间戳
    low[i]表示i或i的子树能回溯到的最早的点的dfn
    */
    int n,m;
    int h[N],e[M],ne[M],idx;
    int low[N],dfn[N],stk[N],top,belong[N],times;
    bool instk[N];
    int scc,size[N];   //强连通分量的个数和大小
    bool sign[M]; 
    
    void add(int a,int b) {
    	e[idx] = b,ne[idx] = h[a],h[a] = idx++;
    }
    
    struct node {
    	int x,y;
    } ans[M];
    int ww;
    
    bool cmp(node a,node b) {
    	if(a.x != b.x)return a.x < b.x;
    	return a.y < b.y;
    }
    
    void tarjan(int u) {
    	low[u] = dfn[u] = ++times;
    	stk[top++] = u;
    	instk[u] = true;
    	for(int i=h[u]; ~i; i=ne[i]) {
    		if(!sign[i]) {
    			sign[i] = sign[i^1] = true;  //标记是否走过
    			int j = e[i];
    			if(!dfn[j]) {
    				tarjan(j);
    				low[u]=min(low[u],low[j]);
    				
    				if(dfn[u] < low[j]) {   //核心 
    					ans[ww].x = min(u,j);
    					ans[ww++].y = max(u,j);
    				}
    			} else if(instk[j])low[u] = min(low[u],dfn[j]);
    		}
    	}
    	if(low[u] == dfn[u]) {
    		scc++;
    		int v;
    		do {
    			v = stk[--top];
    			instk[v] = false;
    			belong[v] = scc;
    			size[scc]++;
    		} while(v != u);
    	}
    }
    
    void work() {
    	n=rd(),m=rd();
    	memset(h,-1,sizeof(h));
    	while(m--) {
    		int a=rd(),b=rd();
    		add(a,b);add(b,a);
    	}
    	memset(dfn,0,sizeof(dfn));
    	memset(instk,false,sizeof(instk));
    	times = top = scc = 0;
    	idx = 0;
    	ww = 0;
    	
    	for(int i=1; i<=n; i++) {
    		if(!dfn[i])tarjan(i);
    	}
    	
    	sort(ans,ans+ww,cmp);
    	for(int i=0; i<ww; i++) {
    		printf("%d %d
    ",ans[i].x,ans[i].y);
    	}
    }
    
    int main() {
    	freopen("in.txt","r",stdin);
    	work();
    	return 0;
    }
    
  • 相关阅读:
    设计模式之GOF23外观模式
    设计模式之GOF23装饰模式
    设计模式之GOF23组合模式
    设计模式之GOF23桥接模式
    设计模式之GOF23代理模式03
    设计模式之GOF23代理模式02
    设计模式之GOF23代理模式01
    设计模式之GOF23适配器模式
    设计模式之GOF23原型模式02
    设计模式之GOF23原型模式01
  • 原文地址:https://www.cnblogs.com/LaiYiC/p/14678482.html
Copyright © 2020-2023  润新知