题意如上,含有重边(重边的话,俩个点就能够构成了边双连通)。

先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少。这里学习了树的直径求法:第一次选随意起点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 无向图中随意加入一条边后使桥的数量最少 / 无向图缩点+求树的直径的更多相关文章

  1. hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

    题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v ...

  2. HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...

  3. HDU-4612 Warm up,tarjan求桥缩点再求树的直径!注意重边

    Warm up 虽然网上题解这么多,感觉写下来并不是跟别人竞争访问量的,而是证明自己从前努力过,以后回头复习参考! 题意:n个点由m条无向边连接,求加一条边后桥的最少数量. 思路:如标题,tarjan ...

  4. HDU4612+Tarjan缩点+BFS求树的直径

    tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...

  5. hdoj3534(树形dp,求树的直径的条数)

    题目链接:https://vjudge.net/problem/HDU-3534 题意:给出一棵树,求树上最长距离(直径),以及这样的距离的条数. 思路:如果只求直径,用两次dfs即可.但是现在要求最 ...

  6. HDU4612 Warm up 边双(重边)缩点+树的直径

    题意:一个连通无向图,问你增加一条边后,让原图桥边最少 分析:先边双缩点,因为连通,所以消环变树,每一个树边都是桥,现在让你增加一条边,让桥变少(即形成环) 所以我们选择一条树上最长的路径,连接两端, ...

  7. hdu-4612(无向图缩点+树的直径)

    题意:给你n个点和m条边的无向图,问你如果多加一条边的话,那么这个图最少的桥是什么 解题思路:无向图缩点和树的直径,用并查集缩点: #include<iostream> #include& ...

  8. 无向图Tarjan&&求树直径

    Tarjan可以用来求无向图的割点和割边 割边:\(dfn[u]<low[v]\) 割点:\(low[v]>=dfn[u]\) 求树的直径 做法1:BFS 从任意一个点开始BFS,然后找到 ...

  9. [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), ...

随机推荐

  1. 定时执行rsync同步数据以及mysql备份

    需求:把机器A中的附件.图片等,备份到备份机B中.将数据库进行备份 附件备份 在A中,启动rsync服务,编辑/etc/xinetd.d/rsync文件,将其中的disable=yes改为disabl ...

  2. 深度学习_2_CNN

    Basic Conception: 感受野(Reception Field) 权值共享(shared weights) 池化,即降采样(sub-Sampling) 卷积核(kernel,filter) ...

  3. 洛谷——1508 Likecloud-吃、吃、吃

    题目背景 问世间,青春期为何物? 答曰:“甲亢,甲亢,再甲亢:挨饿,挨饿,再挨饿!” 题目描述 正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一直处在饥饿的状态中.某日上课,正当他饿得头昏 ...

  4. 洛谷 P3359 改造异或树

    题目描述 给定一棵n 个点的树,每条边上都有一个权值.现在按顺序删掉所有的n-1条边,每删掉一条边询问当前有多少条路径满足路径上所有边权值异或和为0. 输入输出格式 输入格式: 第一行一个整数n. 接 ...

  5. zoj 2615 Cells 栈的运用

    题目链接:ZOJ - 2615 Scientists are conducting research on the behavior of a newly discovered Agamic Cell ...

  6. 【转】【Stackoverflow好问题】去掉烦人的“!=null"(判空语句)

    [Stackoverflow好问题]去掉烦人的“!=null"(判空语句) 问题 为了避免空指针调用,我们经常会看到这样的语句   ...if (someobject != null) { ...

  7. Theam,style

    Theam <!-- Base application theme. --> <!--<style name="AppTheme" parent=" ...

  8. PHP处理Android的POST数据

    今天用PHP开发Android网络数据接口的时候,发现Thinkphp的I函数(php的$_POST)并不能获取到androidpost过来的数据 Android代码如下: Map<String ...

  9. How To Commit Just One Data Block Changes In Oracle Forms

    You have an Oracle Form in which you have multiple data blocks and requirement is to commit just one ...

  10. ci框架文件上传

    控制器类代码 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Upload ex ...