欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

无向图强联通分量-洛谷 P2860 [USACO06JAN]冗余路径Redundant Paths

发布时间:2024/9/5 编程问答 43 豆豆
生活随笔 收集整理的这篇文章主要介绍了 无向图强联通分量-洛谷 P2860 [USACO06JAN]冗余路径Redundant Paths 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

https://www.luogu.org/problem/show?pid=2860
这个就是无向图的强联通;
有向图的两点再一个分量里,是x可以到y,y也可到x;
但无向图本来就是双向的,所以我们再dfs的时候不能直接访问其亲爹;
这样的话,x,y有两条及以上的无共边的路径(就是环),那他们在一个强连通分量里面;

这里{1}{2345}是两个强连通分量;
在这题目里,就是让我们求要添几条变,可以让原图变成一个强连通分量;
那我们先把原图搞一下缩点,无向图缩点后必然会变成一颗树;
树上所有点都互相联通但是无环;
树上必然会产生只有一个儿子的节点;
我们把这些点找出来;
然后以他们为叶子节点弄一个树;
很显然我们只有把这些叶子节点互相连边,就可以形成很多环;
设有N个叶子节点,那我们最少要连(n+1)/2个;
及答案。
为什么?,画画图吧,可以用树的基本特征口胡的;

#include<cstdio>//cfb #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<map> using namespace std; struct cs{ int to,next; }a[20001]; int head[5001],low[5001],tt[5001],q[5001],lin[5001],cc[10001][2],sum[5001]; bool in[5001],f[5001][5001];//f用来判重 int ll,n,m,x,y,z,t,nn,CC,aa,bb,ans,mm; void init(int x,int y){ a[++ll].to=y; a[ll].next=head[x]; head[x]=ll; } void dfs(int x,int y){ tt[x]=++t; low[x]=t; q[++q[0]]=x; in[x]=1; for(int k=head[x];k;k=a[k].next) if(a[k].to!=y){//不回溯亲爹 if(!tt[a[k].to])dfs(a[k].to,x); if(in[a[k].to])low[x]=min(low[x],low[a[k].to]); } if(low[x]==tt[x]){ nn++; while(1){ in[q[q[0]]]=0; lin[q[q[0]]]=nn; q[0]--; if(q[q[0]+1]==x)break; } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); if(!f[x][y])mm++;else continue; f[x][y]=f[y][x]=1; init(x,y); init(y,x); cc[mm][0]=x;cc[mm][1]=y; } for(int i=1;i<=n;i++)if(!tt[i])dfs(i,-1); for(int i=1;i<=mm;i++){ x=cc[i][0];y=cc[i][1]; if(lin[x]==lin[y])continue; sum[lin[x]]++; sum[lin[y]]++;//统计每个点有几个儿子 } for(int i=1;i<=nn;i++)if(sum[i]==1)ans++; printf("%d",(ans+1)/2); }

转载于:https://www.cnblogs.com/largecube233/p/6797933.html

总结

以上是生活随笔为你收集整理的无向图强联通分量-洛谷 P2860 [USACO06JAN]冗余路径Redundant Paths的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。