这道题的总体思路就是找到连通量让它能够看作一个集合,然后找这个集合的度,度数为1的连通量为k,那么需要添加(k+1)/2条边才可以保证边双连通

这里因为一个连通量中low[]大小是相同的,所以我们用ans[low[i]]++来计度数

这道题我最开始按学长的模板来写。。。。MLE到哭了,也不知道这道题为什么这么逗,把5000的数组改成1000也能过,当然后来换了别的思路

为了防止重边的进入,开始设置了一个hash[][]二维数组来判断边是否已经存在,不额外添入

之后,我不采用二维数组,而是在get_bcc函数中利用visit[]一维数组来防止重边的多次访问,也就是说我允许添入多个边,但我不让它多次被访问

这样每循环一次,我就需要更新一次数组,但是空间耗费少了特别多还是很好的。

自己修改多次的代码:

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define N 5005
int k,n,first[N],tmpdfn,dfn[N],low[N],cnt;//isBridge[][]用来判断是否为桥,cnt记载桥的个数 struct Path{
int y,next;
}path[*N];
void add(int x,int y)
{
path[k].y=y,path[k].next=first[x];
first[x]=k;
k++;
}
void dfs(int u,int fa)
{
dfn[u]=low[u]=++tmpdfn;
for(int i=first[u];i!=-;i=path[i].next){
int v=path[i].y;
if(!dfn[v]){
dfs(v,u);
low[u]=min(low[u],low[v]);
}
else if(v!=fa)
low[u]=min(low[u],dfn[v]);
}
} void get_bcc(int n)
{
int visit[N]; cnt=;
int ans[N];
memset(ans,,sizeof(ans));
for(int i=;i<=n;i++){
if(!dfn[i]) dfs(n,-);
}
for(int i=;i<=n;i++){
memset(visit,,sizeof(visit));
for(int j=first[i];j!=-;j=path[j].next){
int v=path[j].y;
if(low[i]!=low[v]&&!visit[v])
ans[low[i]]++,visit[v]=; }
}
for(int i=;i<=n;i++)
if(ans[i]==) cnt++;
}
int main()
{
int R,x,y;
while(scanf("%d%d",&n,&R)!=EOF){ tmpdfn=,k=;
memset(dfn,,sizeof(dfn));
memset(first,-,sizeof(first)); for(int i=;i<R;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x); }
get_bcc(n); printf("%d\n",(cnt+)/);
}
return ;
}

学长的代码,作为模版还是很有价值的:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define maxn 1010
using namespace std; int pre[maxn],dfs_clock,isbridge[maxn][maxn];
vector<int> G[maxn];
bool hash[maxn][maxn]; int dfs1(int u,int fa){
int lowu = pre[u] = ++dfs_clock;
for(int i = ;i < G[u].size();i++){
int v = G[u][i];
if(!pre[v]){
int lowv = dfs1(v,u);
lowu = min(lowu,lowv);
if(lowv > pre[u]){
isbridge[u][v] = isbridge[v][u] = ;
}
}else if(pre[v] < pre[u] && v != fa){
lowu = min(lowu,pre[v]);
}
}
return lowu;
} int fa[maxn],vis[maxn];
int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);} void dfs2(int u){
for(int i = ;i < G[u].size();i++){
int v = G[u][i];
if(!vis[v] && !isbridge[u][v]){
int x = find(u);int y = find(v);
if(x != y) fa[x] = y;
vis[v] = ;
dfs2(v);
}
}
} void find_bcc(int n){
memset(pre,,sizeof(pre));
memset(isbridge,,sizeof(isbridge));
dfs_clock = ;
for(int i = ;i < n;i++)
if(!pre[i]) dfs1(i,-);
for(int i = ;i < n;i++){
if(!vis[i]){
vis[i] = ;
dfs2(i);
}
}
} int degree[maxn];
bool used[maxn]; int main()
{
int n,m;
while(scanf("%d%d",&n,&m) == ){
for(int i = ;i < n;i++){
fa[i] = i;
G[i].clear();
}
memset(hash,,sizeof(hash));
for(int i = ;i < m;i++){
int a,b;
scanf("%d%d",&a,&b);
a--;b--;
if(!hash[a][b]){
G[a].push_back(b);
G[b].push_back(a);
hash[a][b] = hash[b][a] = ;
}
} find_bcc(n); memset(degree,,sizeof(degree));
memset(used,,sizeof(used)); for(int i = ;i < n;i++)
for(int j = ;j < G[i].size();j++){
if(find(i) != find(G[i][j]))
degree[find(G[i][j])]++;
} int sum = ;
for(int i = ;i < n;i++){
int x = find(i);
if(!used[x]){
used[x] = ;
if(degree[x] == ) sum++;
else if(degree[x] == ) sum += ;
}
} int cnt = ;
for(int i = ;i < n;i++){
if(used[i] == ) cnt++;
} if(cnt == ) printf("0\n");
else printf("%d\n",(sum+)/); }
return ;
}

POJ 3177 边双连通求连通量度的问题的更多相关文章

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

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

  2. poj 3177 边双联通 **

    题意:给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图. 链接:点我 kuangbin模板题,分析链接:点我 #include <stdio.h> #include < ...

  3. E - Redundant Paths - poj 3177(缩点求叶子节点)

    题意:给一个图,想让每两个点之间都有两条路相连,不过特殊的是相同的两点之间多次相连被认为是一条边,现在求最少还需要添加几条边才能做到 分析:手欠没看清楚是相同的边只能相连一次,需要去重边,缩点后求出来 ...

  4. poj 3177 Redundant Paths

    题目链接:http://poj.org/problem?id=3177 边双连通问题,与点双连通还是有区别的!!! 题意是给你一个图(本来是连通的),问你需要加多少边,使任意两点间,都有两条边不重复的 ...

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

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

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

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

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

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

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

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

  9. DFS入门之二---DFS求连通块

    用DFS求连通块也是比较典型的问题, 求多维数组连通块的过程也称为--“种子填充”. 我们给每次遍历过的连通块加上编号, 这样就可以避免一个格子访问多次.比较典型的问题是”八连块问题“.即任意两格子所 ...

随机推荐

  1. 机器学习概念之特征选择(Feature selection)之RFormula算法介绍

    不多说,直接上干货! RFormula算法介绍: RFormula通过R模型公式来选择列.支持R操作中的部分操作,包括‘~’, ‘.’, ‘:’, ‘+’以及‘-‘,基本操作如下: 1. ~分隔目标和 ...

  2. PHP生成和获取XML格式数据

    在做数据接口时,我们通常要获取第三方数据接口或者给第三方提供数据接口,而这些数据格式通常是以XML或者JSON格式传输,本文将介绍如何使用PHP生成XML格式数据供第三方调用以及如何获取第三方提供的X ...

  3. Apache Cordova

    http://cordova.apache.org/ Apache Cordova is a platformfor building native mobile applications using ...

  4. Java_静态变量

    class c1c { private static int num = 0; private static double pi = 3.14; private double radius; priv ...

  5. 【转】java序列化一定要应该注意的6个事项!

    1.如果子类实现Serializable接口而父类未实现时,父类不会被序列化,但此时父类必须有个无参构造方法,否则会抛InvalidClassException异常. 2.静态变量不会被序列化,那是类 ...

  6. PE刷题记

    PE 中文翻译 最喜欢做这种很有意思的数学题了虽然数学很垃圾 但是这个网站的提交方式好鬼畜啊qwq 1.Multiples of 3 and 5 直接枚举 2.Even Fibonacci numbe ...

  7. DOCTYPE详解

    什么是DTD? SGML引入了文档类型的概念,并由此引入了文档类型定义(Document Type Definition: DTD).文档类型定义 (DTD) 实际上就是一套关于标记符的语法规则,它包 ...

  8. sc服务查询

    sc query lanmanse2rver |find /i "state" |find /i "running" || ( echo 该服务没有运行时,要执 ...

  9. 纯css滚动公告栏目

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. fork后子进程从哪里开始执行

    子进程和父进程都从调用fork函数的下一条语句开始执行