http://codeforces.com/gym/100712/attachments

题意是给定一个无向图,要求添加一条边,使得最后剩下的桥的数量最小。

注意到在环中加边是无意义的。

那么先把环都缩成一个点,然后重新建立一颗树,找出树的直径就好。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1e5 + ;
struct Edge {
int u, v, tonext;
}e[maxn * ], tree[maxn * ];
int first[maxn], num;
int first_tree[maxn], num_tree;
void addEdge(int u, int v) {
++num;
e[num].u = u, e[num].v = v, e[num].tonext = first[u];
first[u] = num;
}
int DFN[maxn], low[maxn], when, st[maxn], top;
int id[maxn], toSelid;
bool vis[maxn];
void tarjan(int cur, int fa) {
DFN[cur] = low[cur] = ++when; //时间戳
st[++top] = cur; //进栈
vis[cur] = true;
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
if (v == fa) continue;
if (!DFN[v]) { //没访问过
tarjan(v, cur);
low[cur] = min(low[cur], low[v]);
} else if (vis[v]) { // 访问过,而且还在栈里
low[cur] = min(low[cur], DFN[v]);
}
}
if (low[cur] == DFN[cur]) { //这个是强连通分量的根节点。
++toSelid;
do {
id[st[top]] = toSelid; //块id
// sum[toSelId]++; //id节点个数
// printf("%d ", st[top]);
vis[st[top]] = false;
top--;
} while (cur != st[top + ]);
// printf("\n");
}
} void solveTarjan(int n) {
memset(DFN, , sizeof DFN);
memset(low, , sizeof low);
memset(vis, , sizeof vis);
when = top = toSelid = ;
for (int i = ; i <= n; ++i) {
if (!DFN[i]) tarjan(i, i);
}
}
void addEdgeTree(int u, int v) {
++num_tree;
tree[num_tree].u = u, tree[num_tree].v = v, tree[num_tree].tonext = first_tree[u];
first_tree[u] = num_tree;
} struct bfsnode {
int cur, cnt;
bfsnode(int _cur, int _cnt) {
cur = _cur;
cnt = _cnt;
}
};
int tree_diameter(int begin, bool flag) {
memset(vis, , sizeof vis);
queue<struct bfsnode> que;
while (!que.empty()) que.pop();
que.push(bfsnode(begin, ));
vis[begin] = true;
int to = begin, mx = ;
while (!que.empty()) {
struct bfsnode t = que.front();
que.pop();
for (int i = first_tree[t.cur]; i; i = tree[i].tonext) {
int v = tree[i].v;
if (vis[v]) continue;
vis[v] = true;
que.push(bfsnode(v, t.cnt + ));
if (mx < t.cnt + ) {
to = v;
mx = t.cnt + ;
}
}
}
if (flag) return mx;
else return to;
} void work() {
memset(first, , sizeof first);
memset(first_tree, , sizeof first_tree);
num = num_tree = ;
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
solveTarjan(n);
// for (int i = 1; i <= n; ++i) {
// cout << id[i] << " ";
// }
for (int i = ; i <= n; ++i) {
for (int j = first[i]; j; j = e[j].tonext) {
int v = e[j].v;
if (id[i] == id[v]) continue;
addEdgeTree(id[i], id[v]);
addEdgeTree(id[v], id[i]);
}
}
int res = tree_diameter(, );
int di = tree_diameter(res, );
int ans = toSelid - di - ;
ans = max(ans, );
cout << ans << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
int t;
scanf("%d", &t);
while (t--) work();
return ;
}

Bridges Gym - 100712H  无向图的边双连通分量,Tarjan缩点的更多相关文章

  1. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...

  2. tarjan算法求无向图的桥、边双连通分量并缩点

    // tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...

  3. 点/边 双连通分量---Tarjan算法

    运用Tarjan算法,求解图的点/边双连通分量. 1.点双连通分量[块] 割点可以存在多个块中,每个块包含当前节点u,分量以边的形式输出比较有意义. typedef struct{ //栈结点结构 保 ...

  4. HDU4612Warm up 边双连通 Tarjan缩点

    N planets are connected by M bidirectional channels that allow instant transportation. It's always p ...

  5. POJ 3352 无向图边双连通分量,缩点,无重边

    为什么写这道题还是因为昨天多校的第二题,是道图论,HDU 4612. 当时拿到题目的时候就知道是道模版题,但是苦于图论太弱.模版都太水,居然找不到. 虽然比赛的时候最后水过了,但是那个模版看的还是一知 ...

  6. 无向图的边双连通分量(EBC)

    嗯,首先边双连通分量(双连通分量之一)是:在一个无向图中,去掉任意的一条边都不会改变此图的连通性,即不存在桥(连通两个边双连通分量的边),称作边双连通分量.一个无向图的每一个极大边双连通子图称作此无向 ...

  7. [HDOJ4612]Warm up(双连通分量,缩点,树直径)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 所有图论题都要往树上考虑 题意:给一张图,仅允许添加一条边,问能干掉的最多条桥有多少. 必须解决 ...

  8. 无向图的点双连通分量(tarjan模板)

    #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #i ...

  9. UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...

随机推荐

  1. tcpdump 探测器分析

    注:默认情况下,tcpdump临听它遇见的第一个网络接口,如果它选择了错误的接口,可以-i标志强行指定接口,如果DNS不能用,或者只是不希望tcpdump进行名字查找,请使用-n选项,这个选项(-n) ...

  2. 单次目标检测器-SSD简介

    SSD 是使用 VGG19 网络作为特征提取器(和 Faster R-CNN 中使用的 CNN 一样)的单次检测器.我们在该网络之后添加自定义卷积层(蓝色),并使用卷积核(绿色)执行预测. 同时对类别 ...

  3. C语言之数组与指针的易混淆知识点

    一.指针与数组 指针:指针本身也是一个变量,它的内容是指向的内容的地址.指针同样有类型的区分,char 的指针只能指向char型数据,int 指针指向int型数据.但是指针所占内存单元的大小(即其内容 ...

  4. node.js版本管理(Win) --- nvm-window

    目录 1. 安装 2. 使用 1. 安装 去往Git链接:https://github.com/coreybutler/nvm-windows. 点击下载链接: 选择第一个nvm-noinstall. ...

  5. MySQL源码学习——DBUG调试

    一.前言 在规模稍微大点的项目中,为了方便快速找到bug的所在,我们往往需要在代码中加入一些调试用的代码,比如加入一些printf,打印出一些重点的信息:加入assert,进行断言判断.这些比较随意的 ...

  6. HDU1074(状态压缩DP)

    Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  7. CodeForces 1098E. Fedya the Potter

    题目简述:给定长度为$n \leq 5\times 10^4$的序列$a_1, a_2, \dots, a_n \leq 10^5$.将$\gcd(a_l, a_{l+1}, \dots, a_r) ...

  8. 爬取动态网页:Selenium

    参考:http://blog.csdn.net/wgyscsf/article/details/53454910 概述 在爬虫过程中,一般情况下都是直接解析html源码进行分析解析即可.但是,有一种情 ...

  9. Flutter实战视频-移动电商-32.列表页_小类高亮交互效果制作

    32.列表页_小类高亮交互效果制作 点击大类右侧的横向的小类红色显示当前的小类别 解决之前溢出的问题: 先解决一个bug,之前右侧的这里设置的高度是1000,但是有不同的虚拟机和手机设别的问题造成了溢 ...

  10. 11.ClientCredential模式总结

    11.ClientCredential模式总结 服务端定义的Resource叫做api Resource API默认是被保护的 第三方的客户端先去请求 Server拿到access token.带着t ...