POJ 3177 边双连通求连通量度的问题
这道题的总体思路就是找到连通量让它能够看作一个集合,然后找这个集合的度,度数为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 边双连通求连通量度的问题的更多相关文章
- poj 3177 Redundant Paths【求最少添加多少条边可以使图变成双连通图】【缩点后求入度为1的点个数】
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11047 Accepted: 4725 ...
- poj 3177 边双联通 **
题意:给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图. 链接:点我 kuangbin模板题,分析链接:点我 #include <stdio.h> #include < ...
- E - Redundant Paths - poj 3177(缩点求叶子节点)
题意:给一个图,想让每两个点之间都有两条路相连,不过特殊的是相同的两点之间多次相连被认为是一条边,现在求最少还需要添加几条边才能做到 分析:手欠没看清楚是相同的边只能相连一次,需要去重边,缩点后求出来 ...
- poj 3177 Redundant Paths
题目链接:http://poj.org/problem?id=3177 边双连通问题,与点双连通还是有区别的!!! 题意是给你一个图(本来是连通的),问你需要加多少边,使任意两点间,都有两条边不重复的 ...
- POJ 3177 Redundant Paths(边双连通的构造)
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13717 Accepted: 5824 ...
- tarjan算法求桥双连通分量 POJ 3177 Redundant Paths
POJ 3177 Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12598 Accept ...
- POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)
POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的.一份代码能交.给定一个连通无向图,问加几条边能使得图变成一个双连通图 ...
- POJ 3177——Redundant Paths——————【加边形成边双连通图】
Redundant Paths Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Sub ...
- DFS入门之二---DFS求连通块
用DFS求连通块也是比较典型的问题, 求多维数组连通块的过程也称为--“种子填充”. 我们给每次遍历过的连通块加上编号, 这样就可以避免一个格子访问多次.比较典型的问题是”八连块问题“.即任意两格子所 ...
随机推荐
- background-origin与background-clip的“区别”
css3新增了一些背景相关的属性,其中background-origin与background-clip是比较让人困惑的: background-origin:用于指定绘制背景图片的起点.默认值:pa ...
- Windows下降权MYSQL和apche的运行级别(普通用户权限运行)
1.MYSQL的降权运行 新建立一个用户比如mysql net user mysql microsoft /add net localgroup users mysql /del 不属于任何组 ...
- k-window的关闭与打开设置
// 打开弹框窗口 public showKwinDow() { const that = this as any; // 设置窗口居中 that.$refs['setAddEdit'].widget ...
- strict说明
- vue-gemini-scrollbar(vue组件-自定义滚动条)
vue-gemini-scrollbar(vue组件-自定义滚动条) https://segmentfault.com/a/1190000013338560
- 阿里云人脸比对API封装
这是根据封装是根据阿里云官方给的Demo进行修改的,当时是因为编写微信小程序云函数需要使用到阿里云人脸比对接口,才对其进行封装的. 记录下来,方便下次使用. 复制下来可以直接使用. 用到的依赖如下: ...
- NET实现谷歌OCR的使用记录(CLOUD VISION API)
1)购买VPS 2)配置一VPN 建议使用 cisco anycounect | ***会连接失败(切记,祭奠浪费的一天)大神可以帮我看下是什么问题 3)进入https://cloud.goog ...
- django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module
pip3 install mysqlclient try again python manage.py makemigrations python manage.py migrate
- web中的$多种意思
$符号在php中是表示变量的特征字符, 在js中它也有很多作用, 一般我们用来命名一个函数名称,获取id的1.首先可以用来表示变量, 比如变量 var s='asdsd'或var $s='asdasd ...
- 【mybatis】mybatis数据源源码剖析(JNDI、POOLED、UNPOOLED)
一.概述 二.创建 mybatis数据源的创建过程稍微有些曲折. 1. 数据源的创建过程: 2. mybatis支持哪些数据源,也就是dataSource标签的type属性可以写哪些合法的参数? 弄清 ...