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 ...
- 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 ...
- hdoj3534(树形dp,求树的直径的条数)
题目链接:https://vjudge.net/problem/HDU-3534 题意:给出一棵树,求树上最长距离(直径),以及这样的距离的条数. 思路:如果只求直径,用两次dfs即可.但是现在要求最 ...
- HDU4612 Warm up 边双(重边)缩点+树的直径
题意:一个连通无向图,问你增加一条边后,让原图桥边最少 分析:先边双缩点,因为连通,所以消环变树,每一个树边都是桥,现在让你增加一条边,让桥变少(即形成环) 所以我们选择一条树上最长的路径,连接两端, ...
- hdu-4612(无向图缩点+树的直径)
题意:给你n个点和m条边的无向图,问你如果多加一条边的话,那么这个图最少的桥是什么 解题思路:无向图缩点和树的直径,用并查集缩点: #include<iostream> #include& ...
- 无向图Tarjan&&求树直径
Tarjan可以用来求无向图的割点和割边 割边:\(dfn[u]<low[v]\) 割点:\(low[v]>=dfn[u]\) 求树的直径 做法1:BFS 从任意一个点开始BFS,然后找到 ...
- [LeetCode] Number of Connected Components in an Undirected Graph 无向图中的连通区域的个数
Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...
随机推荐
- css 之 position定位
position属性一共有4个值,分别是static.absolute.relative.fixed. static为默认值,指块保持在原本应该在的位置上,即该值没有任何移动的效果. absolute ...
- ie8实现无刷新文件上传
ie8由于无法使用FormData,想要无刷新上传文件就显得比较麻烦.这里推荐使用jQuery-File-Upload插件,它能够很方便的解决ie8无刷新文件上传问题.(最低兼容到ie6) jQuer ...
- 牛客网 牛客小白月赛2 G.文
G.文 链接:https://www.nowcoder.com/acm/contest/86/G 这个题wa了一发,有点智障,浮点数,式子里面要*1.0,忘了,然后wa了,改了就过了(脑子有坑) 代码 ...
- centos 7 mysql 离线安装教程
1. 解压下载的zip包,会发现有以下几个rpm包: MySQL-client-advanced-5.6.22-1.el7.x86_64.rpm MySQL-devel-advanced-5.6.22 ...
- JAVA基础之集合、Iterator迭代器、泛型及增强for循环
个人理解: 对于集合,首先要明确的是最顶层的接口是Collection接口类,其包含一些基本的方法以便子类调用,不过在定义的时候最好定义好数据类型,以免遍历时还得必须进行向上转型:特别注意的是其没有关 ...
- mysql事物隔离级别
mysql实现了四种隔离级别 Read Uncommitted(未提交读) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少.读取 ...
- pt-query-digest 实践(转)
mysql slowlog 使用与介绍 slow_query_log =1-----是否打开 slow_query_log_file = /data/mysql_data/node-1/mysql-s ...
- ios iPhone 如何将应用程序名称本地化
iPhone的应用程序名称也可以本地化,可以按照以下步骤来实施: 1. 修改项目目录下的’ -info.plist’文件名 将’ -info.plist’ 修改为 Info.plist 2. 将Inf ...
- C# 计算一串字符串算法
工作中遇到一个小问题,就是要做一个类似excel那种的公式的东西,就是A0+A1*B0那样的公式,然后得出结果. 首先,分析. 这不是计算器,计算器要比这个简易,计算器是所按即所得,即你点击+-之类的 ...
- 关于embedding-深度学习基本操作 【Word2vec, Item2vec,graph embedding】
https://zhuanlan.zhihu.com/p/26306795 https://arxiv.org/pdf/1411.2738.pdf https://zhuanlan.zhihu.com ...