题目链接: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. [Android]使用button切换TextView可见和不可见

    <Button android:id="@+id/btnTest" android:layout_width="match_parent" android ...

  2. 【转】C# windows服务的创建与调试

    Windows Service这一块并不复杂,但是注意事项太多了,网上资料也很凌乱,偶尔自己写也会丢三落四的.所以本文也就产生了,本文不会写复杂的东西,完全以基础应用的需求来写,所以不会对Window ...

  3. Python2和Python3共存安装robotframework

    1.下载Python2.Python3安装包 https://www.python.org/ 2.下载pip.tar.gz https://pypi.python.org/pypi/pip#downl ...

  4. 病毒的侵扰和再侵扰两道AC自动机的应用

    HDU2896 病毒的侵扰 http://vjudge.net/problem/viewProblem.action?id=16404 题目大意: 记录每个病毒的编号,并给出一些网站的源码,分别输出网 ...

  5. middle(bzoj 2653)

    Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...

  6. SQL SERVER 2012 第三章 使用INSERT语句添加数据

    INSERT [TOP (<expression>) [PERCENT] [INTO] <tabular object>[(column list)][OUTPUT <o ...

  7. python学习之-- assert断言

    assert 断言作用:断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假.可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常.举例如下:a ...

  8. THUPC2018看题总结

    THUPC2018看题总结 #6387. 「THUPC2018」绿绿与串串 / String 据说是签到题啊. 首先根据题目的意思,我们发现如果能找到那个最后一次选择的对称轴岂不是美滋滋. 自然地,我 ...

  9. 洛谷——P2820 局域网

    P2820 局域网 题目背景 某个局域网内有n(n<=100)台计算机,由于搭建局域网时工作人员的疏忽,现在局域网内的连接形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成 ...

  10. spring mvc get请求也可以接受DTO对象

    spring mvc get请求也可以接受DTO对象,比如:url上面你还是将参数&符号连接起来,并自动封装进一个DTO对象里. 只有@RequestBody注解spring mvc才会从ht ...