/**
problem: http://poj.org/problem?id=3177
tarjan blog: https://blog.csdn.net/reverie_mjp/article/details/51704523 v 为下一结点, u为当前结点
如果low[v] > dfn[u] 则 边(u,v)为桥
缩点后剩下的所有边都为桥(缩点后即为树结构)
将叶子结点相连使其成为双联通分量为最优解
所以:
添加(leaf + 1) / 2 条边即可使图成为双联通图
**/
#include<stdio.h>
#include<stack>
#include<algorithm>
using namespace std; class Graphics{
const static int MAXN = ;
const static int MAXM = * ;
private:
struct Edge{
int to, next;
bool bridge;
}edge[MAXM];
struct Point{
int dfn, low, color;
}point[MAXN];
int first[MAXN], sign, sumOfPoint, dfnNum, colorNum;
bool vis[MAXN];
stack<int> stk;
void tarjan(int u, int preEdge = -){
point[u].low = dfnNum;
point[u].dfn = dfnNum ++;
vis[u] = true;
stk.push(u);
for(int i = first[u]; i != -; i = edge[i].next){
int to = edge[i].to;
if((i^) == preEdge) continue; /// 由于是双向边,防止由该边跑回原来的点
if(!point[to].dfn){
tarjan(to, i);
point[u].low = min(point[u].low, point[to].low);
if(point[to].low > point[u].dfn){
edge[i].bridge = true;
edge[i^].bridge = true;
}
}else if(vis[to]){
point[u].low = min(point[to].dfn, point[u].low);
}
}
if(point[u].dfn == point[u].low){
vis[u] = false;
point[u].color = ++ colorNum;
while(stk.top() != u){
point[stk.top()].color = colorNum;
vis[stk.top()] = false;
stk.pop();
}
stk.pop();
}
}
public:
void init(int n){
sumOfPoint = n;
for(int i = ; i <= n; i ++){
first[i] = -;
vis[i] = ;
}
sign = colorNum = ;
dfnNum = ;
}
void addEdgeOneWay(int u, int v){
edge[sign].to = v;
edge[sign].next = first[u];
edge[sign].bridge = false;
first[u] = sign ++;
}
void addEdgeTwoWay(int u, int v){
addEdgeOneWay(u, v);
addEdgeOneWay(v, u);
}
void tarjanAllPoint(){
for(int i = ; i <= sumOfPoint; i ++){
if(!point[i].dfn)
tarjan(i);
}
}
int getAns(){
int *degree = new int[sumOfPoint+];
int ans = ;
for(int i = ; i <= sumOfPoint; i ++){
degree[i] = ;
}
tarjanAllPoint();
for(int i = ; i <= sumOfPoint; i ++){
for(int j = first[i]; j != -; j = edge[j].next){
int to = edge[j].to;
if(edge[j].bridge){
degree[point[to].color] ++;
}
}
}
for(int i = ; i <= sumOfPoint; i ++){
if(degree[i] == ){
ans ++;
}
}
delete []degree; return (ans + ) / ;
}
}graph; int main(){
int f, r;
scanf("%d%d", &f, &r);
graph.init(f);
while(r --){
int a, b;
scanf("%d%d", &a, &b);
graph.addEdgeTwoWay(a, b);
}
printf("%d\n", graph.getAns());
return ;
}

ps:

防止由该边跑回原来的点不能判断(点)而要判断(边)即

这么写是有bug的
例如:重边

poj 3177 Redundant Paths 求最少添加几条边成为双联通图: tarjan O(E)的更多相关文章

  1. tarjan算法求桥双连通分量 POJ 3177 Redundant Paths

    POJ 3177 Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12598   Accept ...

  2. POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)

    POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的.一份代码能交.给定一个连通无向图,问加几条边能使得图变成一个双连通图 ...

  3. poj 3177 Redundant Paths(tarjan边双连通)

    题目链接:http://poj.org/problem?id=3177 题意:求最少加几条边使得没对点都有至少两条路互通. 题解:边双连通顾名思义,可以先求一下连通块显然连通块里的点都是双连通的,然后 ...

  4. poj 3177 Redundant Paths【求最少添加多少条边可以使图变成双连通图】【缩点后求入度为1的点个数】

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11047   Accepted: 4725 ...

  5. POJ 3177 Redundant Paths(边双连通的构造)

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13717   Accepted: 5824 ...

  6. POJ 3177——Redundant Paths——————【加边形成边双连通图】

    Redundant Paths Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Sub ...

  7. POJ 3177 Redundant Paths (tarjan边双连通分量)

    题目连接:http://poj.org/problem?id=3177 题目大意是给定一些牧场,牧场和牧场之间可能存在道路相连,要求从一个牧场到另一个牧场要有至少两条以上不同的路径,且路径的每条pat ...

  8. POJ 3177 Redundant Paths(Tarjan)

    题目链接 题意 : 一个无向连通图,最少添加几条边使其成为一个边连通分量 . 思路 :先用Tarjan缩点,缩点之后的图一定是一棵树,边连通度为1.然后找到所有叶子节点,即度数为1的节点的个数leaf ...

  9. POJ - 3177 Redundant Paths (边双连通缩点)

    题意:在一张图中最少可以添加几条边,使其中任意两点间都有两条不重复的路径(路径中任意一条边都不同). 分析:问题就是最少添加几条边,使其成为边双连通图.可以先将图中所有边双连通分量缩点,之后得到的就是 ...

随机推荐

  1. linux基础-wget、apt-get、yum的区别

    Linux操作系统下安装与下载软件是Linux非常基本也非常重要的命令,分清wget.apt-get.yum的区别很重要. Linux操作系统主要分为两大类: RedHat系列:Redhat.Cent ...

  2. 重构指南 - 引入参数对象(Introduce Parameter Object)

    当一个方法的参数超过3个以上,就可以考虑将参数封装成一个对象.将参数封装成对象后提高了代码的可读性,并且该参数对象也可以供多个方法调用,以后如果增加删除参数,方法本身不需要修改,只需要修改参数对象就可 ...

  3. C# 矩阵运算和一些基本的几何运算

    以前工作中写的,这里备个份,有可能用到 基本的矩阵运算类,测试20阶以内应该没啥问题,超过20阶不好使... /// <summary> /// 矩阵 异常 512索引 1024无解 20 ...

  4. ssh-keygen使用

    ssh-keygen 作用就是验证主机和用户公钥加密 值得注意的是passphrase选项询问 是对自身密钥的保护,因为在ssh通信前,密钥是不受保护的,如果填来的话通常会使用aes256-cbc的对 ...

  5. CRM——销售与客户

    一.销售与客户——表结构 1.客户类型 (1)公共客户(公共资源) 必备条件:没有报名: 在必备条件满足的情况下,满足以下任意条件都是公共客户: 3天没有跟进:15天没有成单. (2)我的客户 原销售 ...

  6. webstrom 在脚本区域写其他语言得到语法提示

    webstrom 在脚本区域写其他语言得到语法提示 webstrom 的提示小灯泡 点击inject language or reference 选择相应的语言. 如果写的内容比较多, 可以按照web ...

  7. 【转】成型滤波与匹配滤波的MATLAB实现

    转载自:https://blog.csdn.net/yuan1164345228/article/details/45919315 Fd=1; Fs=8; Delay=3; R=0.5; [yf,tf ...

  8. 爬虫之绘图matplotlib与词云(七)

    1 绘制条形图 import matplotlib # 数据可视化 from matplotlib import pyplot as plt # 配置字体 matplotlib.rcParams[&q ...

  9. Selenium2学习(六)-- 定位神器CSS

    前言 大部分人在使用selenium定位元素时,用的是xpath定位,因为xpath基本能解决定位的需求.css定位往往被忽略掉了,其实css定位也有它的价值,css定位更快,语法更简洁.这一篇css ...

  10. LAB2 软件测试 Selenium上机实验 2017

    1.安装SeleniumIDE插件 打开Firefox——>菜单栏——>附加组件——>获取附加组件——>查看更多附加组件——>搜索框输入SeleniumIDE并查找——& ...