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. linux应用之apache服务的安装及配置(centos)

    CentOS Apache服务器安装与配置   一.安装Apache程序,一般有三种安装方式:1.直接网络安装:2.下载rpm包,上传至服务器进行安装:3.通过原代码编译安装: yum -y inst ...

  2. Android工程的目录结构

    1.最大限度的将不需要出现在Java代码中的文件和代码本身分离开来 2.使用XML标记语言定义UI和数据结构 3.对于工程中的文件存储在工程目录中的那个位置有着严格的规定,在编译过程中Android会 ...

  3. 骨牌覆盖问题 KxM

    前面我们说了一些简单的骨牌覆盖问题,有了上面的经验,我们可以尝试解决K*M的 思路和上一篇文章所提到的3*N的 很类似: 依然是矩阵快速幂.我们需要把一个小的边固定下来作为的已知边,然后进行矩阵快速幂 ...

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

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

  5. bzoj 4503 两个串 —— FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4503 推式子即可: 不知怎的调了那么久,应该是很清晰的. 代码如下: #include< ...

  6. 4.java变量

    1.java中如何定义变量的语言 数据类型 变量名:2.如何给变量赋值 语言 变量名=值:3.变量本质是什么. 本质就是内存中的一块空间,这块空间有‘类型’.“名字”.“值” int a;//在内存中 ...

  7. raspberry安装go

    参考官方文档:https://golang.org/doc/install/source (因为被墙)可以看国内地址: http://godoc.golangtc.com/doc/install/so ...

  8. Firebug 的脚本页面不能用

    1.遇到这种情况,一般重置firebug,然后开启“脚本“功能,刷新页面,就能显示正常 2.要不就是 版本问题,50.0不行,下载回49版本就可以了

  9. 微信小程序开发之页面数据绑定

    js:Page( { data:{ parmer:"",             //字符串参数 userinfo:{      userphone:"",   ...

  10. UVaLive 3695 Distant Galaxy (扫描线)

    题意:给平面上的 n 个点,找出一个矩形,使得边界上包含尽量多的点. 析:如果暴力那么就是枚举上下边界,左右边界,还得统计个数,时间复杂度太高,所以我们考虑用扫描线来做,枚举上下边界, 然后用其他方法 ...