poj 3352 Road Construction (无向图edge-BCC缩点)
2015-06-27 19:45
295 查看
题目大意:无向简单图,添加尽量少的边使得图为边-双连通。输出最少需要添加的边条数。
这儿有个结论:对于一棵树,至少添加(其叶子节点+1)/2条边,便可得到一个边-双连通图。在网上找了很久,没有找到严格的证明。不过可以这样理解:对于一棵树,首先可以找到它的直径(或者公共祖先最远的两个叶子节点),对于直径两端的叶子节点连一条边,这样可以尽可能多地使得桥数目减少。然后再找剩下的叶子节点中公共祖先最远的两个,再连一条边,依次下去。得到的结果就是那样。
根据这个结论就比较容易想到解法了:先进行BCC缩点,转换为一颗树,然后统计该树中度数为1的节点个数(叶子节点),根据结论便可得到答案。
求BCC的写法与SCC的写法大致一样,只是加了个参数,防止对一条无向边访问两次。
这儿有个结论:对于一棵树,至少添加(其叶子节点+1)/2条边,便可得到一个边-双连通图。在网上找了很久,没有找到严格的证明。不过可以这样理解:对于一棵树,首先可以找到它的直径(或者公共祖先最远的两个叶子节点),对于直径两端的叶子节点连一条边,这样可以尽可能多地使得桥数目减少。然后再找剩下的叶子节点中公共祖先最远的两个,再连一条边,依次下去。得到的结果就是那样。
根据这个结论就比较容易想到解法了:先进行BCC缩点,转换为一颗树,然后统计该树中度数为1的节点个数(叶子节点),根据结论便可得到答案。
求BCC的写法与SCC的写法大致一样,只是加了个参数,防止对一条无向边访问两次。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<stack> using namespace std; #define N 200005 struct Edge{ int to,next; bool flag; }edge[2000005]; int dfn ,low ,bccno ,head ,bridge_num,cnt,dfs_clock,bcc_cnt; stack<int> S; void add(int u,int v){ edge[cnt].flag=0; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } void dfs(int u,int fa){ dfn[u]=low[u]=++dfs_clock; S.push(u); for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].to; if(v==fa) continue; //保证由一条无向边拆成的两条有向边只访问一条 if(!dfn[v]){ dfs(v,u); low[u]=min(low[u],low[v]);//用后代的low函数更新自身 if(low[v]>dfn[u]){ ++bridge_num; edge[i].flag=edge[i^1].flag=1; } } else if(!bccno[v]){ low[u]=min(low[u],dfn[v]);//用反向边更新 } } if(low[u]==dfn[u]){ ++bcc_cnt; for(;;){ int x=S.top();S.pop(); bccno[x]=bcc_cnt; if(x==u) break; } } } void find_bcc(int n){ dfs_clock=bcc_cnt=bridge_num=0; memset(bccno,0,sizeof(bccno)); memset(dfn,0,sizeof(dfn)); for(int i=0;i<n;++i) if(!dfn[i]) dfs(i,-1); } int deg ; int main() { int n,m,i,j,x,y; while(~scanf("%d%d",&n,&m)) { memset(head,-1,sizeof(head)); memset(deg,0,sizeof(deg)); cnt=0; for(i=0;i<m;++i){ scanf("%d%d",&x,&y); add(--x,--y); add(y,x); } find_bcc(n); for(i=0;i<n;++i){ for(j=head[i];~j;j=edge[j].next){ if(edge[j].flag) deg[bccno[i]]++; } } int ans=0; for(i=1;i<=bcc_cnt;++i) if(deg[i]==1) ++ans; printf("%d\n",(ans+1)/2); } return 0; }
相关文章推荐
- Hadoop优化 第一篇 : HDFS/MapReduce
- 十、C# 异常处理
- hihocoder题库1000
- Number of Islands (leetcode)
- 欢迎使用CSDN-markdown编辑器
- 九、C# 合式类型
- JavaScript创建对象的几种方式
- 黑马程序员——Java基础——基本概念
- hdu 2082 找单词
- android菜鸟学习笔记6----android布局(一)
- java中的匿名内部类总结
- Facebook IV Winner's Interview: 1st place, Peter Best (aka fakeplastictrees)
- J2EE编辑中的中文乱码解决问题
- Restful WebService简单介绍
- Leveldb/lmdb/comdb 各种存储引擎的个人见解
- servlet 跳转
- [Linux]在终端启动程序关闭终端不退出的方法
- 【编程题】01串排序
- 虚拟机NAT模式下上网
- Coursera台大机器学习课程笔记11 -- Nonlinear Transformation