题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4612

Warm up

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 7206    Accepted Submission(s): 1681

Problem Description
  N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel between any two planets through these channels.
  If we can isolate some planets from others by breaking only one channel , the channel is called a bridge of the transportation system.
People don't like to be isolated. So they ask what's the minimal number of bridges they can have if they decide to build a new channel.
  Note that there could be more than one channel between two planets.
 
Input
  The input contains multiple cases.
  Each case starts with two positive integers N and M , indicating the number of planets and the number of channels.
  (2<=N<=200000, 1<=M<=1000000)
  Next M lines each contains two positive integers A and B, indicating a channel between planet A and B in the system. Planets are numbered by 1..N.
  A line with two integers '0' terminates the input.
 
Output
  For each case, output the minimal number of bridges after building a new channel in a line.
 
Sample Input
4 4
1 2
1 3
1 4
2 3
0 0
 
Sample Output
0
 
Author
SYSU
 
Source
 
Recommend
zhuyuanchen520
 
 
题解:
1.用Tarjan算法求出每个边双联通分量,由于每一对点之间可以有多条边,所以在判断边是否被重复访问时,需要依据边的下标而定 。
2.对每个边双联通分量进行缩点,缩点之后得到的是一棵无根树。
3.在树上添加一条边,使得桥的数目减少最多。最多能减少多少呢?树上最长路。
 
 
vector建树:
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 2e5+; struct Edge
{
int to, next;
}edge[MAXN*];
int tot, head[MAXN];
vector<int>g[MAXN]; void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} int index, dfn[MAXN], low[MAXN];
int top, Stack[MAXN], instack[MAXN];
int block, belong[MAXN]; void Tarjan(int u, int pre)
{
dfn[u] = low[u] = ++index;
Stack[top++] = u;
instack[u] = true;
for(int i = head[u]; i!=-; i = edge[i].next)
{
//因为一对点之间可能有多条边,所以不能根据v是否为上一个点来防止边是否被重复访问。而需要根据边的编号
if((i^)==pre) continue;
int v = edge[i].to;
if(!dfn[v])
{
Tarjan(v, i);
low[u] = min(low[u], low[v]);
}
else if(instack[v])
low[u] = min(low[u], dfn[v]);
} if(low[u]==dfn[u])
{
block++;
int v;
do
{
v = Stack[--top];
instack[v] = false;
belong[v] = block;
}while(v!=u);
}
} int diameter, endpoint;
int dfs(int u, int pre, int dep)
{
if(dep>diameter) { endpoint = u; diameter = dep; }
for(int i = ; i<g[u].size(); i++)
if(g[u][i]!=pre)
dfs(g[u][i], u, dep+);
} void init(int n)
{
tot = ;
memset(head, -, sizeof(head)); index = ;
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low)); top = ;
memset(instack, false, sizeof(instack)); block = ;
for(int i = ; i<=n; i++)
belong[i] = i, g[i].clear();
} int main()
{
int n, m;
while(scanf("%d%d", &n, &m) && (n||m) )
{
init(n);
for(int i = ; i<=m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
} Tarjan(, -);
for(int u = ; u<=n; u++)
for(int i = head[u]; i!=-; i = edge[i].next)
{
int v = edge[i].to;
if(belong[u]!=belong[v])
g[belong[u]].push_back(belong[v]);
} endpoint = , diameter = ;
dfs(, -, );
dfs(endpoint, -, );
printf("%d\n", block--diameter);
}
}
前向星建树:
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 2e5+; struct Edge
{
int from, to, next;
}edge[MAXN*];
int tot, head[MAXN]; void addedge(int u, int v)
{
edge[tot].from = u;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} int index, dfn[MAXN], low[MAXN];
int top, Stack[MAXN], instack[MAXN];
int block, belong[MAXN]; void Tarjan(int u, int pre)
{
dfn[u] = low[u] = ++index;
Stack[top++] = u;
instack[u] = true;
for(int i = head[u]; i!=-; i = edge[i].next)
{
//因为一对点之间可能有多条边,所以不能根据v是否为上一个点来防止边是否被重复访问。而需要根据边的编号
if((i^)==pre) continue;
int v = edge[i].to;
if(!dfn[v])
{
Tarjan(v, i);
low[u] = min(low[u], low[v]);
}
else if(instack[v])
low[u] = min(low[u], dfn[v]);
} if(low[u]==dfn[u])
{
block++;
int v;
do
{
v = Stack[--top];
instack[v] = false;
belong[v] = block;
}while(v!=u);
}
} int diameter, endpoint;
int dfs(int u, int pre, int dep)
{
if(dep>diameter) { endpoint = u; diameter = dep; }
for(int i = head[u]; i!=-; i = edge[i].next)
if(edge[i].to!=pre)
dfs(edge[i].to, u, dep+);
} void init(int n)
{
tot = ;
memset(head, -, sizeof(head)); index = ;
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low)); top = ;
memset(instack, false, sizeof(instack)); block = ;
for(int i = ; i<=n; i++)
belong[i] = i;
} int main()
{
int n, m;
while(scanf("%d%d", &n, &m) && (n||m) )
{
init(n);
for(int i = ; i<=m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
} Tarjan(, -);
tot = ;
memset(head, -, sizeof(head));
for(int i = ; i<*m; i++)
{
int u = edge[i].from, v = edge[i].to;
if(belong[u]!=belong[v])
addedge(belong[u], belong[v]);
} endpoint = , diameter = ;
dfs(, -, );
dfs(endpoint, -, );
printf("%d\n", block--diameter);
}
}
 

HDU4612 Warm up —— 边双联通分量 + 重边 + 缩点 + 树上最长路的更多相关文章

  1. POJ-3352-RoadConstruction(边双联通分量,缩点)

    链接:https://vjudge.net/problem/POJ-3352#author=0 题意: 给一个无向连通图,至少添加几条边使得去掉图中任意一条边不改变图的连通性(即使得它变为边双连通图) ...

  2. HDU4738 Caocao's Bridges —— 边双联通分量 + 重边

    题目链接:https://vjudge.net/problem/HDU-4738 A network administrator manages a large network. The networ ...

  3. [J]computer network tarjan边双联通分量+树的直径

    https://odzkskevi.qnssl.com/b660f16d70db1969261cd8b11235ec99?v=1537580031 [2012-2013 ACM Central Reg ...

  4. 【UVA10972】RevolC FaeLoN (求边双联通分量)

    题意: 给你一个无向图,要求把所有无向边改成有向边,并且添加最少的有向边,使得新的有向图强联通. 分析: 这题的解法还是很好想的.先用边双联通分量缩点,然后找新图中入度为0和为1的点,入度为0则ans ...

  5. ARC062 - F. Painting Graphs with AtCoDeer (Polya+点双联通分量)

    似乎好久都没写博客了....赶快来补一篇 题意 给你一个 \(n\) 个点 , 没有重边和自环的图 . 有 \(m\) 条边 , 每条边可以染 \(1 \to k\) 中的一种颜色 . 对于任意一个简 ...

  6. POJ2942 Knights of the Round Table【Tarjan点双联通分量】【二分图染色】【补图】

    LINK 题目大意 有一群人,其中有一些人之间有矛盾,现在要求选出一些人形成一个环,这个环要满足如下条件: 1.人数大于1 2.总人数是奇数 3.有矛盾的人不能相邻 问有多少人不能和任何人形成任何的环 ...

  7. lightoj 1300 边双联通分量+交叉染色求奇圈

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1300 边双连通分量首先dfs找出桥并标记,然后dfs交叉着色找奇圈上的点.这题只要求在 ...

  8. HDU5409---CRB and Graph 2015多校 双联通分量缩点

    题意:一个联通的无向图, 对于每一条边, 若删除该边后存在两点不可达,则输出这两个点, 如果存在多个则输出第一个点尽可能大,第二个点尽可能小的. 不存在输出0 0 首先 若删除某一条边后存在多个联通分 ...

  9. poj2942(双联通分量,交叉染色判二分图)

    题意:一些骑士,他们有些人之间有矛盾,现在要求选出一些骑士围成一圈,圈要满足如下条件:1.人数大于1.2.总人数为奇数.3.有仇恨的骑士不能挨着坐.问有几个骑士不能和任何人形成任何的圆圈. 思路:首先 ...

随机推荐

  1. Oracle获取最近执行的SQL语句

    注意:不是每次执行的语句都会记录(如果执行的语句是能在该表找到的则ORACLE不会再次记录,就是说本次执行的语句和上次或者说以前的语句一模一样则下面语句就查不出来的): select last_loa ...

  2. 04004_使用JavaScript完成注册表单数据校验

    1.需求分析 (1)用户在进行注册的时候会输入一些内容,但是有些用户会输入一些不合法的内容,这样会导致服务器的压力过大,此时我们需要对用户输入的内容进行一个校验(前端校验和后台校验): (2)前端校验 ...

  3. BeautifulSoup4系列二

    前言 本篇详细介绍beautifulsoup4的功能,从最基础的开始讲起,让小伙伴们都能入门 一.读取HTML页面 1.先写一个简单的html页面,把以下内容copy出来,保存为html格式文件 &l ...

  4. var声明的成员变量和函数内声明的变量区别

    1.函数内部,有var声明的是局部变量,没var的,声明的全局变量. 2.在全局作用域内声明变量时,有var 和没var声明的都是全局变量,是window的属性.通过变量var声明全局对象的属性无法通 ...

  5. Go 方法和接收者

    package main import ( "fmt" ) //面向对象 //go仅支持封装,不支持继承和多态 //go语言中没有class,只要struct //不论地址还是结构 ...

  6. python去掉BOM头的方法

    今天在写批量生成身份证号造数据的时候出现了问题,其中一个是报不能转成int型,后经查找,发现是utf-8BOM头的问题. 什么是BOM? 在utf-8编码文件中BOM在文件头部,占用三个字节,用来标示 ...

  7. eclipse pom.xml 报错org.apache.maven.plugin.war.WarMojo的解决办法

    如题,maven项目eclipse提示pom.ml有错,提示信息就是org.apache.maven.plugin.war.WarMojo. 然后执行 maven install 出现如下错误提示 [ ...

  8. SpringBoot Beans管理和自动配置

    原 SpringBoot Beans管理和自动配置 火推 02 2017年12月20日 21:37:01 阅读数:220 SpringBoot Beans管理和自动配置 @SpringBootAppl ...

  9. vi/vim复制粘贴命令

    1. 选定文本块.使用v进入可视模式,移动光标键选定内容. 2.复制的命令是y,即yank(提起) ,常用的命令如下:     y      在使用v模式选定了某一块的时候,复制选定块到缓冲区用:   ...

  10. 10.1——pair,map,set,multimap,multiset

    map和set只允许相同的键出现一次,而multimap和multiset则允许出现多次. 1. 引言——pair类型: pair需要添加头文件utility头文件 make_pair<v1,v ...