RevolC FaeLoN UVA
来源:互联网 发布:经纬度定位软件ios 编辑:程序博客网 时间:2024/06/05 17:20
RevolC FaeLoN UVA - 10972
图论·边-双连通分量
http://blog.csdn.net/l123012013048/article/details/47373065
题目大意:
把无向图的每一条边变成一条有向边,形成一个并加入最少的有向边,让新图称为一个强连通分量。问最小加边数。
题解:
求出所有的边-双连通分量,把他们缩点,得到多棵无根树森林。
树上的点是边-双连通分量,边是桥。
对于一个连通块,如果它的节点个数>1:
统计出树中度为1的节点的个数,即为叶节点的个数,记为leaf。则至少在树上添加(leaf+1)/2条边,就能使树达到边二连通,所以至少添加的边数就是(leaf+1)/2。具体方法为,首先把两个最近公共祖先最远的两个叶节点之间连接一条边,这样可以把这两个点到祖先的路径上所有点收缩到一起,因为一个形成的环一定是双连通的。然后再找两个最近公共祖先最远的两个叶节点,这样一对一对找完,恰好是(leaf+1)/2次,把所有点收缩到了一起。
另外,两个连通块的互相连接并不需要额外的边。
只要把给他们加的边各自拆开一条,就能把他们连起来连到一起。
对于一个孤立的点,它需要一条边:
如果有n个点,要求在这n个点间添加有向边,使得这n个点变成强连通,那么需要添加的边的数量为n,均摊每个点一条。
有了上面这个结论,求的时候就比较好办了,处理的时候,只需要统计出所有度为1和度为0的缩点的数量即可 。
假设度为1的数量为A (叶子结点,连通图里面的)
度为2的数量为B(孤立的点)
那么所需要连的边就是(A + 1) / 2 + B
注意求边-双连通分量的时候,不能把当前u取出来,而是只取到v。
在dfs外面要把栈里剩下的元素作为一个新的双联通分量。
Code:
#include <iostream>#include <cstdio>#include <cstring>#include <stack>#include <vector>#define MP make_pair#define D(x) cout<<#x<<" = "<<x<<" "#define E cout<<endlusing namespace std;typedef pair<int,int> pii;const int N = 2017;const int M = 20017;int n,m;struct Edge{ int u,v,next;}e[M];int head[N], ec=0;void clear(){ memset(head,0,sizeof(head)); ec=0; }void add(int a,int b){ ec++; e[ec].u=a; e[ec].v=b; e[ec].next=head[a]; head[a]=ec;}int belong[N],bridge[M][2],low[N],dfn[N],du[N],tim,bcc_cnt,bridge_cnt;stack<int> s; void dfs(int u,int pa){ low[u]=dfn[u]=++tim; s.push(u); for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(!dfn[v]){ dfs(v,u); low[u]=min(low[u],low[v]); if(low[v]>dfn[u]){ bridge_cnt++; bridge[bridge_cnt][0]=u; bridge[bridge_cnt][1]=v; bcc_cnt++; while(true){ int x=s.top(); s.pop(); belong[x]=bcc_cnt; if(x==v) break; } } } else if(dfn[v]<dfn[u] && v!=pa){ low[u]=min(low[u],dfn[v]); } }}void find_bcc(){ bcc_cnt=0; tim=0; bridge_cnt=0; memset(dfn,0,sizeof(dfn)); memset(belong,0,sizeof(belong)); for(int i=1;i<=n;i++){ if(!dfn[i]){ dfs(i,-1); bcc_cnt++; while(!s.empty()){ int x=s.top(); s.pop(); belong[x]=bcc_cnt; } } }}int main(){ freopen("a.in","r",stdin); while(~scanf("%d%d",&n,&m) && (n||m)){ clear(); int a,b; for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); add(a,b); add(b,a); } find_bcc();// D(bcc_cnt); E;// for(int i=1;i<=n;i++){// D(belong[i]);// } E; if(bcc_cnt==1){ printf("0\n"); continue; } memset(du,0,sizeof(du)); for(int i=1;i<=bridge_cnt;i++){ du[belong[bridge[i][0]]]++; du[belong[bridge[i][1]]]++; }// for(int i=1;i<=bcc_cnt;i++) D(du[i]); E; int A=0,B=0; for(int i=1;i<=bcc_cnt;i++){ if(du[i]==1) A++; if(du[i]==0) B++; }// D(ans); E; printf("%d\n",(A+1)/2+B); }}
- Uva-10972-RevolC FaeLoN
- RevolC FaeLoN UVA
- uva 10972 RevolC FaeLoN (双连通分量)
- uva 10972 - RevolC FaeLoN(双联通)
- uva 10972 - RevolC FaeLoN(边双连通分量)
- UVA 10972 RevolC FaeLoN(边-双连通+缩点)
- UVA 10972 - RevolC FaeLoN(边-双连通分量)
- UVA -- 10972 RevolC FaeLoN(边双连通)
- UVA - 10972 RevolC FaeLoN (边双连通分量)
- Uva 10972 RevolC FaeLoN(边双连通分量)
- UVA 10972 RevolC FaeLoN(边双联通+缩点)
- UVA10972 RevolC FaeLoN
- (intermediate)DFS (边-双连通) UVA 10972 RevolC FaeLoN
- UVA10972 - RevolC FaeLoN(双连通分量)
- uva
- UVA
- UVA
- UVA
- MIME邮件的multipart类型与text类型的区别
- 关于C++中虚函数表存放位置的思考
- 修改Gradle使用国内源
- 简单说说python import与from...import....(python模块)
- Java8学习笔记 — 新日期时间API
- RevolC FaeLoN UVA
- java多线程学习之停止休眠中的线程问题
- 自定义jsp标签示例
- POJ 1339 poker card game 笔记
- Oracle数据库学习---其他函数及转换函数
- 跨域传值即主页面与iframe之间互相传值
- angularjs之ui-grid 使用详解
- 修改Android手机主机名
- startActivityForResult+onActivityResult