• 冗余路径 Redundant Paths e-DCC缩点


    冗余路径 Redundant Paths

    题目传送

    sol:

    如果两点间存在至少两条不重复的路径,这说明他们两点在同一个边双连通分量(不存在割边)。

    那么可以进行e-DCC的缩点,得到一棵树。

    对于这棵树广泛意义上的叶子节点(度数为1)而言,都还至少需要一条边连向他。

    那么可以贪心的一次连两个叶子节点,答案显然就是(cnt+1>>1)

    #include<bits/stdc++.h>
    #define IL inline
    #define RG register
    #define DB double
    #define LL long long
    using namespace std;
    
    const int N=5005;
    const int M=1e4+5;
    
    int n,m,tot,cnt,leaf,Time,head[N],bel[N],vis[N],low[N],dfn[N],bri[M<<1];
    
    struct edge{int x,y;}s[M];
    struct EDGE{int next,to;}e[M<<1];
    
    IL int gi() {
    	RG int x=0,p=1; RG char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') p=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
    	return x*p;
    }
    
    IL void New() {
    	tot=0;
    	memset(&e,0,sizeof(e));
    	memset(head,0,sizeof(head));
    }
    
    IL void make(int a,int b) {
    	e[++tot]=(EDGE){head[a],b},head[a]=tot;
    	e[++tot]=(EDGE){head[b],a},head[b]=tot;
    }
    
    void Tarjan(int x,int fx) {
    	RG int i,y;
    	dfn[x]=low[x]=++Time;
    	for(i=head[x];i;i=e[i].next) {
    		if(!dfn[y=e[i].to]) {
    			Tarjan(y,x),low[x]=min(low[x],low[y]);
    			if(low[y]>dfn[x]) bri[i]=bri[i^1]=1; 
    		}
    		else if(y!=fx) low[x]=min(low[x],dfn[y]);
    	}	
    }
    
    void dfs(int x) {
    	RG int i,y;
    	bel[x]=cnt,vis[x]=1;
    	for(i=head[x];i;i=e[i].next)
    		if(!vis[y=e[i].to]&&!bri[i]) dfs(y);
    }
    
    void dfs2(int x,int fx) {
    	RG int i,y,fl=0;
    	for(i=head[x];i;i=e[i].next)
    		if((y=e[i].to)!=fx) fl=1,dfs2(y,x);
    	if(!fl) ++leaf;
    }
    
    int main()
    {
    	RG int i,b=0;
    	n=gi(),m=gi(),tot=1;
    	for(i=1;i<=m;++i)
    		s[i].x=gi(),s[i].y=gi(),make(s[i].x,s[i].y);
    	for(i=1,Tarjan(1,0);i<=n;++i)
    		if(!vis[i]) ++cnt,dfs(i);
    	if(cnt==1) return puts("0"),0;
    	for(i=1,New();i<=m;++i)
    		if(bel[s[i].x]!=bel[s[i].y]) make(bel[s[i].x],bel[s[i].y]);
    	dfs2(1,0);
    	for(i=head[1];i;i=e[i].next) ++b;
    	if(b==1) ++leaf;
    	printf("%d
    ",leaf+1>>1);
    	return 0;
    }
    
  • 相关阅读:
    spoj 694 求一个字符串中不同子串的个数
    Qt for Android 开发大坑
    HDUOJ A Mathematical Curiosity 1017
    Node.js开发入门—HelloWorld再分析
    GTK入门学习:布局容器之固定布局
    彻底领悟javascript中的exec与match方法
    JQuery中attr属性和jQuery.data()学习笔记
    正则表达式-验证带千分号的,带任意位小数的数字类型
    JQuery EasyUI 动态改变表单项的验证守则
    JavaScript计算两个日期的时间差
  • 原文地址:https://www.cnblogs.com/Bhllx/p/11258322.html
Copyright © 2020-2023  润新知