HDU 4612 Warm up (边双连通分量+缩点+树的直径)
<题目链接>
题目大意:
给出一个连通图,问你在这个连通图上加一条边,使该连通图的桥的数量最小,输出最少的桥的数量。
解题分析:
首先,通过Tarjan缩点,将该图缩成一颗树,树上的每个节点都是一个边双连通分量,树上的每条边都是桥,现在需要挑出两个点,将它们直接相连,这样它们原始路径上所有的桥因为形成了环而全部消失,因此为了使剩下的桥最少,我们需要找到路径上桥最多的两点,又由于缩点后,树的每条边都是桥,所以这里就转化为树上距离两点的最远距离,也就是求树的直径。
下面Tarjan的时候需要注意的是,vis记录的是访问过边的编号不是节点的编号。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef pair<int, int> pll;
;
;
int num, num1, top, cnum,maxdis, pos,cnt;
int head[N], head1[N], dis[N],instk[N], stk[N], dfn[N], low[N], belong[N];
];
struct Edge{
int to, next;
}e[M<<], e1[M<<];
void add(int u, int v) {
e[num].to = v, e[num].next = head[u], head[u] = num++;
}
void add1(int u, int v) {
e1[num1].to = v, e1[num1].next = head1[u], head1[u] = num1++;
}
void init() {
num = num1 = cnt = cnum = top = ;
mem(head,-),mem(head1,-),mem(belong,),mem(instk,);
mem(vis,),mem(stk,),mem(dfn,),mem(low,),mem(dis,);
}
pll edge[M];
void tarjan(int u){
dfn[u] = low[u] = ++cnt;
instk[u] = ;
stk[++top] = u;
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].to;
if(vis[i])continue;
vis[i] = vis[i^] = ; //将正、反两边全部标记
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(instk[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u]) {
++cnum; //cnum为边双连通分量的数量
int v;
do{
v = stk[top--];
instk[v] = ;
belong[v] = cnum; //将该连通块染色
} while(v != u);
}
}
void bfs(int u){
queue <int> q;
q.push(u);
dis[u] = ;
mem(vis,);
vis[u] = ;
maxdis = , pos = u;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head1[u]; ~i; i = e1[i].next) {
int v = e1[i].to;
if(vis[v])continue;
vis[v] = ;
dis[v] = dis[u]+;
if(dis[v]>maxdis) { //更新树上的最远距离
maxdis = dis[v];
pos = v; //并且记录下该点
}
q.push(v);
}
}
}
int main()
{
int n, m, x, y;
while(scanf("%d%d",&n,&m)!=EOF,n||m){
init();
; i<m; i++) {
scanf("%d%d", &x, &y);
edge[i].first = x, edge[i].second = y; //记录下所有的边,用结构体记录也可以
add(x, y),add(y, x);
}
tarjan();
;
; i<m; i++){ //将缩点后的所有点建图,跑BFS,求树的直径
int x = edge[i].first, y = edge[i].second;
if(belong[x]!=belong[y]) {
add1(belong[x], belong[y]);
add1(belong[y], belong[x]);
edgenum++; //桥的数量+1
}
}
bfs(belong[]);
bfs(pos); //求出此时树的直径,即一条路径上所含的最多桥的数量
int ans = edgenum-maxdis;
printf("%d\n", ans);
}
}
2018-11-07
HDU 4612 Warm up (边双连通分量+缩点+树的直径)的更多相关文章
- HDU 4612 Warm up(双连通分量缩点+求树的直径)
思路:强连通分量缩点,建立一颗新的树,然后求树的最长直径,然后加上一条边能够去掉的桥数,就是直径的长度. 树的直径长度的求法:两次bfs可以求,第一次随便找一个点u,然后进行bfs搜到的最后一个点v, ...
- hdu4612 Warm up[边双连通分量缩点+树的直径]
给你一个连通图,你可以任意加一条边,最小化桥的数目. 添加一条边,发现在边双内是不会减少桥的.只有在边双与边双之间加边才有效.于是,跑一遍边双并缩点,然后就变成一棵树,这样要加一条非树边,路径上的点( ...
- HDU 4612 Warm up (边双连通分量+DP最长链)
[题意]给定一个无向图,问在允许加一条边的情况下,最少的桥的个数 [思路]对图做一遍Tarjan找出桥,把双连通分量缩成一个点,这样原图就成了一棵树,树的每条边都是桥.然后在树中求最长链,这样在两端点 ...
- Gym - 100676H H. Capital City (边双连通分量缩点+树的直径)
https://vjudge.net/problem/Gym-100676H 题意: 给出一个n个城市,城市之间有距离为w的边,现在要选一个中心城市,使得该城市到其余城市的最大距离最短.如果有一些城市 ...
- hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Su ...
- hdu 4612 Warm up 双连通缩点+树的直径
首先双连通缩点建立新图(顺带求原图的总的桥数,事实上因为原图是一个强连通图,所以桥就等于缩点后的边) 此时得到的图类似树结构,对于新图求一次直径,也就是最长链. 我们新建的边就一定是连接这条最长链的首 ...
- HDU-4612 Warm up 边双连通分量+缩点+最长链
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 简单图论题,先求图的边双连通分量,注意,此题有重边(admin还逗比的说没有重边),在用targ ...
- hdu4612(双连通缩点+树的直径)
传送门:Warm up 题意:询问如何加一条边,使得剩下的桥的数目最少,输出数目. 分析:tarjan缩点后,重新建图得到一棵树,树上所有边都为桥,那么找出树的直径两个端点连上,必定减少的桥数量最多, ...
- HDU 4612 Warm up(2013多校2 1002 双连通分量)
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Su ...
随机推荐
- Windows 批处理大全(附各种实例)
Windows 批处理大全(附各种实例) 2009年07月19日 21:31:00 阅读数:2552 批处理文件是无格式的文本文件,它包含一条或多条命令.它的文件扩展名为 .bat 或 .cmd.在命 ...
- Confluence 6 缓存性能优化
Confluence 的运行状态与缓存状态有这密切的关系.针对 Confluence 的管理员来说,尤其是大型站点的 Confluence 管理员,设置好缓存尤其显得关键. 希望修改缓存的大小: 进入 ...
- Confluence 6 隐藏人员目录
人员目录提供了你 Confluence 中所有用户的列表. 如果你希望禁用人员目录,请在你应用程序命令行中的 Configuring System Properties 进行设置. 希望为匿名用户禁用 ...
- Confluence 6 降级你的许可证
如果你决定降级你 Confluence 的许可证而削减你的许可证开支,你需要确定当前已经直排的用户许可证数量(在用户许可证页面中)要少于你希望应用的新的许可证的允许用户数量,在你应用新许可证的时候. ...
- map函数和reduce函数的区别
①从参数方面来讲:map()函数: map()包含两个参数,第一个是参数是一个函数,第二个是序列(列表或元组).其中,函数(即map的第一个参数位置的函数)可以接收一个或多个参数.reduce()函数 ...
- 微信浏览器发送ajax请求执行多次解决方法
http://www.cnblogs.com/whatlonelytear/p/8934738.html
- hdu4044 依赖背包变形 好题!
由于不是求最大的可拦截的HP值,而是要将最小值最大化,那么就需要分配每个子树用的钱数以达到最小值最大化 第一步解决如何分配钱使得结点u的子树中用了j元钱后可以拦截的HP最大,这就是变形的分组(依赖)背 ...
- node.js 框架express有关于router的运用
1.express 路由入门 const express = require('express'); let server = express(); server.listen(8087); //用户 ...
- Chrome浏览器常用键盘快捷键介绍
很多人喜欢使用键盘快捷键来操作电脑,因为在熟练的情况下,使用键盘会比使用鼠标点击更快.更高效.本文对Chrome浏览器常用的快捷键做个说明. 标签页和窗口快捷键 1. Ctrl + n 打开新窗口 ...
- mysql 查看某个数据库中所有表的数据量
1.登录mysql 2.使用命令:use information_schema; 3.使用命令:select table_name,table_rows from tables where TABLE ...