题意:一个无向图,问建立一条新边以后桥的最小数量。

  分析:缩点以后,找出新图的树的直径,将这两点连接即可。

  但是题目有个note:两点之间可能有重边!而用普通的vector保存边的话,用v!=fa的话是没办法让重边访问的,因此,使用数组模拟邻接表的方法来储存边。

这样,只要访问了一条边以后,令E[i].vis=E[i^1].vis=1即可,这样可以防止无向图的边和重边搞混。原理就是按位异或,一个奇数^1变为比它小1的偶数,反之亦然:如5^1=4,4^1=5。

  具体见代码:

 #include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stack>
#include <vector>
#include <set>
#include <queue>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; const int N = +; int n,m,dfn[N],low[N];
int head[N];
int tot=;
int dfs_clock;
int bridge;
int belong[N];
int scc_cnt;
int maxd;
bool vis[N];
vector<int> G[N];
stack<int> S; struct edge
{
int v;
int vis;
int nxt;
}E[*+]; void addEdge(int u,int v)
{
E[tot].v=v;
E[tot].vis=;
E[tot].nxt=head[u];
head[u]=tot++; E[tot].v=u;
E[tot].vis=;
E[tot].nxt=head[v];
head[v]=tot++;
} void tarjan(int u)
{
dfn[u]=low[u]=++dfs_clock;
S.push(u);
for(int i=head[u];i!=-;i=E[i].nxt)
{
int v = E[i].v;
if(E[i].vis) continue;
E[i].vis=E[i^].vis=; if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]); if(low[v]>dfn[u]) bridge++;
}
else if(!belong[v])
{
low[u]=min(low[u],dfn[v]);
}
} if(dfn[u]==low[u])
{
scc_cnt++;
for(;;)
{
int x = S.top();S.pop();
belong[x] = scc_cnt;
if(x==u) break;
}
}
} void init()
{
memset(head,-,sizeof(head));
tot=;
memset(dfn,,sizeof(dfn));
dfs_clock=;
bridge=;
memset(belong,,sizeof(belong));
scc_cnt=;
maxd=;
for(int i=;i<=n;i++) G[i].clear();
memset(vis,,sizeof(vis));
} //找到树的直径
void findMaxDeep(int u,int deep)
{
vis[u]=; maxd=max(maxd,deep);
for(int i=;i<G[u].size();i++)
{
int v = G[u][i];
if(!vis[v])
{
findMaxDeep(v,deep+);
}
}
} //用bfs来找到一个叶子节点
int findRoot()
{
queue<int> Q;
Q.push();
vis[]=;
int last=;
while(!Q.empty())
{
int x = Q.front();Q.pop();
for(int i=;i<G[x].size();i++)
{
int v = G[x][i];
if(!vis[v])
{
Q.push(v);
vis[v]=;
last=v;
}
}
}
return last;
} void solve()
{
for(int i=;i<=n;i++) if(!dfn[i]) tarjan(i); //重新建图
for(int i=;i<=n;i++)
{
for(int j=head[i];j!=-;j=E[j].nxt)
{
int v = E[j].v;
int x = belong[i];
int y = belong[v];
if(x!=y)
{
G[x].push_back(y);
G[y].push_back(x);
}
}
} int root=findRoot();
memset(vis,,sizeof(vis)); findMaxDeep(root,); printf("%d\n",bridge-maxd);
} int main()
{
while(scanf("%d%d",&n,&m)==)
{
if(n== && m==) break;
init(); for(int i=;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v);
} solve();
}
}

  但是奇怪的是,重新建图以后找叶子节点的时候,这里用G[x].size()==2不能够实现。讲道理,原理上是没错的,尽管后来发现如果缩点后只有一个点的话是个例外,但是即使排除了这个特殊情况仍然不行,,,这个问题也留着以后探讨吧。。

HDU 4612 Warm up —— (缩点 + 求树的直径)的更多相关文章

  1. 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。

    问加一条边,最少可以剩下几个桥. 先双连通分量缩点,形成一颗树,然后求树的直径,就是减少的桥. 本题要处理重边的情况. 如果本来就两条重边,不能算是桥. 还会爆栈,只能C++交,手动加栈了 别人都是用 ...

  2. F - Warm up - hdu 4612(缩点+求树的直径)

    题意:有一个无向连通图,现在问添加一条边后最少还有几个桥 分析:先把图缩点,然后重构图为一棵树,求出来树的直径即可,不过注意会有重边,构树的时候注意一下 *********************** ...

  3. HDU 4612 Warm up(双连通分量缩点+求树的直径)

    思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...

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

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

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

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

  6. (求树的直径)Warm up -- HDU -- 4612

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 给一个无向图, 加上一条边后,求桥至少有几个: 那我们加的那条边的两个顶点u,v:一定是u,v之 ...

  7. hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】

    Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Su ...

  8. HDU 4612 Warm up (边双连通分量+缩点+树的直径)

    <题目链接> 题目大意:给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量. 解题分析: 首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点 ...

  9. HDU 4612——Warm up——————【边双连通分量、树的直径】

    Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Stat ...

随机推荐

  1. OkHttp3 + retrofit2 封装

    0.下载文件 1.gradle 添加 compile 'com.squareup.retrofit2:retrofit:2.1.0'compile 'com.squareup.retrofit2:co ...

  2. mysql5.7 密码字段名更改

    由password更改为authentication_string update user set authentication_string=password("123456") ...

  3. hexo发布后样式丢失

    修改配置中url路径,和root,问题解决.

  4. LeetCode:178.分数排名

    题目链接:https://leetcode-cn.com/problems/rank-scores/ 题目 编写一个 SQL 查询来实现分数排名.如果两个分数相同,则两个分数排名(Rank)相同.请注 ...

  5. cv2.videocapture()失败,无法读取视频

    原因:缺少ffmpeg的支持 解决:一般opencv3.3版本及以上支持ffmpeg,实验4.1.0成功 pip install opencv-python pip install opencv-co ...

  6. Delphi 重载方法与重定义方法

  7. Flutter——Padding组件

    在 html 中常见的布局标签都有 padding 属性,但是 Flutter 中很多 Widget 是没有 padding 属性.这个时候我们可以用 Padding 组件处理容器与子元素直接的间距. ...

  8. V.24 V.35 ISDN E1 POS这些常见的广域网接口

    转:http://blog.sina.com.cn/s/blog_bc1c78600101l2ss.html 广域网(Wide Area Network)是一种跨地区的数据通讯网络,通常是一个局域网到 ...

  9. Djang简介

    一:MVC简介 MVC的全拼为Model-View-Controller,最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语 ...

  10. 图像处理---《Mat对象 与 IplImage对象》

    图像处理---<认识 Mat对象> Mat对象 与 IplImage对象 (1)Mat对象:OpenCV2.0之后引进的图像数据结构.自动分配内存.不存在内存泄漏的问题,是面向对象的数据结 ...