hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径
题意如上,含有重边(重边的话,俩个点就可以构成了边双连通)。
先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少。这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径。(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v;若u不是直径上一点,设u到直径上的一点为x,同理易证。
最后 缩点后树的边-直径即可。
再说说这次,哎,先是爆栈,没有在C++申请空间。。。 无向图的tarjian太不熟练了!很久没敲了。。。。
注意点:无向图求边双连通,缩点,可以这样:
法1:必需用前向星来保存边,然后标记访问边(同时标记反向边)的方法来处理。这样,重边的话,就在字自然在一个边通分量中了。(要求边数可以用数组存下),这样不用!=-father来判断。
法2,重边视为单边(只有俩个点不连通),不标记边,多一个参数father,在返祖边更新我的时候,加判断!=father。
#pragma comment(linker, "/STACK:10240000000000,10240000000000") //申请空间
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<stack>
using namespace std;
const int maxv=300010;
int dfn[maxv];int low[maxv];int visited[maxv];
int ins[maxv];stack<int>sta;int scc[maxv];
int times=0;int block=0;
int n,m;
int minn(int a,int b)
{
if(a<=b)return a;
return b;
}
int nume=0;int e[2000500][2];int head[maxv];
void inline adde(int i,int j) //原图
{
e[nume][0]=j;e[nume][1]=head[i];head[i]=nume++;
e[nume][0]=i;e[nume][1]=head[j];head[j]=nume++;
}
int nume2=0;int newg[2000500][2];int head2[maxv];
void inline adde2(int i,int j) //新图
{
newg[nume2][0]=j;newg[nume2][1]=head2[i];head2[i]=nume2++;
newg[nume2][0]=i;newg[nume2][1]=head2[j];head2[j]=nume2++;
}
bool marke[2001000]; //标记边的访问
void tarjan(int u)
{
dfn[u]=low[u]=++times;
ins[u]=1;
sta.push(u);
for(int i=head[u];i!=-1;i=e[i][1])
{
int child=e[i][0];
if(marke[i])continue; //注意放在这里,否则下面的会更新,起不了作用
if(visited[child]==0)
{
visited[child]=1;
marke[i]=marke[i^1]=1; //标记双向
tarjan(child);
low[u]=minn(low[u],low[child]);
}
else if(ins[child])
{
low[u]=minn(dfn[child],low[u]);
}
}
if(low[u]==dfn[u]) //同一个边双连通
{
block++;
int cur;
do
{
cur=sta.top();
ins[cur]=0;
sta.pop();
scc[cur]=block;
}while(cur!=u);
}
}
void rebuild()
{
for(int i=1;i<=n;i++) //遍历所有边,来重新建图,若在同一个边双连通中,则有边。
{
for(int j=head[i];j!=-1;j=e[j][1])
{
int ch=e[j][0];
if(scc[i]!=scc[ch])
adde2(scc[i],scc[ch]);
}
}
}
int lev[maxv];
void bfsgetlev(int ss) //BFS分层
{
memset(lev,0,sizeof(lev));
memset(visited,0,sizeof(visited));
queue<int>q;
q.push(ss);
visited[ss]=1;
while(!q.empty())
{
int cur=q.front();
q.pop();
for(int i=head2[cur];i!=-1;i=newg[i][1])
{
int vv=newg[i][0];
if(!visited[vv])
{
lev[vv]=lev[cur]+1;
q.push(vv);
visited[vv]=1;
}
}
}
return ;
}
void init()
{ block=times=0;nume=0;nume2=0;
memset(marke,0,sizeof(marke));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(visited,0,sizeof(visited));
memset(head,-1,sizeof(head));
memset(head2,-1,sizeof(head2)); }
int main()
{
while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
{
init();
int a,b;
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
adde(a,b);
}
visited[1]=1;
tarjan(1);
rebuild();
int ans=0;
bfsgetlev(1);
int froms=0;
int maxx=-1;
for(int i=1;i<=block;i++)
{
if(lev[i]>maxx)
{
maxx=lev[i];
froms=i;
}
}
bfsgetlev(froms); //最远点(直直径的一个端点)
for(int i=1;i<=block;i++)
{
if(lev[i]>maxx)
{
maxx=lev[i];
}
}
ans=block-1-maxx;
printf("%d\n",ans); }
return 0;
}
hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径的更多相关文章
- hdu4612 无向图中随意加入一条边后使桥的数量最少 / 无向图缩点+求树的直径
题意如上,含有重边(重边的话,俩个点就能够构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选随意起点U,进行bfs,到达最远的一个点v ...
- python中pip添加国内镜像源后显著加速下载
python中pip添加国内镜像源后显著加速下载 更换pip源到国内镜像,很多国外的库下载非常慢,添加国内镜像后安装下载速度提升非常明显(亲测有些可以由几十kb加速到几MB) pip国内的一些镜像阿里 ...
- HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
- HDU-4612 Warm up,tarjan求桥缩点再求树的直径!注意重边
Warm up 虽然网上题解这么多,感觉写下来并不是跟别人竞争访问量的,而是证明自己从前努力过,以后回头复习参考! 题意:n个点由m条无向边连接,求加一条边后桥的最少数量. 思路:如标题,tarjan ...
- HDU4612+Tarjan缩点+BFS求树的直径
tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...
- poj 3177 Redundant Paths【求最少添加多少条边可以使图变成双连通图】【缩点后求入度为1的点个数】
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11047 Accepted: 4725 ...
- 为什么不能在scrollview中直接添加一个image,然后使animation.begin()??
http://stackoverflow.com/questions/17267451/animation-cant-begin-in-scrollview-in-windows-phone 以上是我 ...
- hdoj3534(树形dp,求树的直径的条数)
题目链接:https://vjudge.net/problem/HDU-3534 题意:给出一棵树,求树上最长距离(直径),以及这样的距离的条数. 思路:如果只求直径,用两次dfs即可.但是现在要求最 ...
- HDU4612 Warm up 边双(重边)缩点+树的直径
题意:一个连通无向图,问你增加一条边后,让原图桥边最少 分析:先边双缩点,因为连通,所以消环变树,每一个树边都是桥,现在让你增加一条边,让桥变少(即形成环) 所以我们选择一条树上最长的路径,连接两端, ...
随机推荐
- pb2.text_format.Merge(f.read(), self.solver_param) AttributeError: 'module' object has no attribute 'text_format'
http://blog.csdn.net/qq_33202928/article/details/72526710
- spfa模板+讲解
zz http://blog.sina.com.cn/s/blog_6ad20aef0100mc1a.html Spfa算法 (模板源代码) 这是Bellman Ford的改进算法. 算法介绍: ...
- IIS应用程序池"启用32位"导致服务不可用的503错误
原来运行正常的站点,突然不正常了,出现503错误.查看操作系统的日志查看器显示: 由于配置问题,无法加载模块 DLL“C:\Program Files (x86)\IIS\Asp.Net Core M ...
- chosen选择框加载数据
1.单选$(select).val($("#id").val());$(select).trigger("chosen:updated"); 2.多选 func ...
- Linux C++/C开发所必需的一系列工具
系统平台下的开发工具.开发环境各有不同.Linux C++/C开发所必需的一系列工具: 1. vi(vim)文本编辑器一个UNIX世界标准的文本编辑器,简约而强大,不论作为开发人员还是系统管理员,熟练 ...
- RedHat7搭建KVM虚拟机
RedHat7搭建KVM虚拟机 1. 宿主机安装RedHat7.3系统 1.1选择语言 中文.简体中文(中国) 1.2安装位置 1.2.1自定义分区,选择LVM,将分区空间全部分配给根 1.2.2禁用 ...
- Centos6.9 搭建rsync服务端与客户端 案例:全网备份项目
rsync的企业工作场景说明 1)定时备份 1.1生产场景集群架构服务器备份方案项目 借助cron+rsync把所有客户服务器数据同步到备份服务器 2)实时复制 本地数据传输模式(local-only ...
- php-7.0.16 , apache2.4.25 配置
官网下载php,apache 修改apache E:\php\Apache24\conf\httpd.conf Define SRVROOT "E:/php/Apache24" - ...
- Hive和Hbase整合
Hive只支持insert和delete操作,并不支持update操作,所以无法实施更新hive里的数据,而HBASE正好弥补了这一点,所以在某些场景下需要将hive和hbase整合起来一起使用. 整 ...
- jq相关操作
1事件: <div class="ele">123</div> box.onclick = function(ev){ ev:系统传入的事件对象 ele.i ...