题意:有n个点,m条路,问你最少加几条边,让整个图变成边双连通分量。

思路:缩点后变成一颗树,最少加边 = (度为1的点 + 1)/ 2。3177有重边,如果出现重边,用并查集合并两个端点所在的缩点后的点。

代码:

/**/
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = + ;
const int seed = ;
const ll MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
using namespace std;
struct Edge{
int u, v, next;
}edge[maxn << ];
int index, scc_cnt, tot; //scc_cnt记录SCC
int dfn[maxn], low[maxn], sccno[maxn], in[maxn], head[maxn];
stack<int> s;
void addEdge(int u, int v){
edge[tot].v = v;
edge[tot].u = u;
edge[tot].next = head[u];
head[u] = tot++;
}
void tarjan(int u, int pre){
dfn[u] = low[u] = ++index;
s.push(u);
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].v;
if(!dfn[v]){
tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else if(v != pre){
low[u] = min(low[u], dfn[v]);
}
}
if(dfn[u] == low[u]){
scc_cnt++;
int a;
while(){
a=s.top();
s.pop();
sccno[a] = scc_cnt;
if(a == u) break;
}
}
} int main(){
int n, m;
scanf("%d%d", &n, &m);
index = scc_cnt = tot = ;
while(!s.empty()) s.pop();
memset(head, -, sizeof(head));
memset(dfn, , sizeof(dfn));
memset(sccno, , sizeof(sccno));
for(int i = ; i < m; i++){
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
for(int i = ; i <= n; i++){
if(!dfn[i])
tarjan(i, );
}
memset(in, , sizeof(in));
for(int i = ; i < tot; i += ){
int u = edge[i].u, v = edge[i].v;
if(sccno[u] != sccno[v]){
in[sccno[u]]++;
in[sccno[v]]++;
}
}
int cnt = ;
for(int i = ; i <= scc_cnt; i++){
if(in[i] == ) cnt++;
}
printf("%d\n", (cnt + ) / );
return ;
}
/**/
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = + ;
const int seed = ;
const ll MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
using namespace std;
struct Edge{
int u, v, next;
}edge[maxn << ];
int index, scc_cnt, tot; //scc_cnt记录SCC
int dfn[maxn], low[maxn], sccno[maxn], in[maxn], head[maxn];
stack<int> s;
map<int, int> mp[maxn];
int Find(int x){
return sccno[x] == x? x : sccno[x] = Find(sccno[x]);
}
void addEdge(int u, int v){
edge[tot].v = v;
edge[tot].u = u;
edge[tot].next = head[u];
head[u] = tot++;
}
void tarjan(int u, int pre){
dfn[u] = low[u] = ++index;
s.push(u);
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].v;
if(!dfn[v]){
tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else if(v != pre){
low[u] = min(low[u], dfn[v]);
}
}
if(dfn[u] == low[u]){
scc_cnt++;
int a;
while(){
a=s.top();
s.pop();
sccno[a] = u;
if(a == u) break;
}
}
} int main(){
int n, m;
scanf("%d%d", &n, &m);
index = scc_cnt = tot = ;
while(!s.empty()) s.pop();
memset(head, -, sizeof(head));
memset(dfn, , sizeof(dfn));
memset(sccno, , sizeof(sccno));
for(int i = ; i < m; i++){
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
for(int i = ; i <= n; i++){
if(!dfn[i])
tarjan(i, );
}
for(int i = ; i <= n; i++) mp[i].clear();
memset(in, , sizeof(in));
for(int i = ; i < tot; i += ){
int u = edge[i].u, v = edge[i].v;
if(u > v) swap(u, v);
mp[u][v]++;
if(mp[u][v] == ){
int fx = Find(u), fy = Find(v);
if(fx != fy){
sccno[fx] = fy;
}
}
}
for(int i = ; i < tot; i += ){
int u = edge[i].u, v = edge[i].v;
int fx = Find(u), fy = Find(v);
if(fx != fy){
in[fx]++;
in[fy]++;
}
}
int cnt = ;
for(int i = ; i <= n; i++){
if(sccno[i] == i && in[i] == ) cnt++;
}
printf("%d\n", (cnt + ) / );
return ;
}

poj3352 Road Construction & poj3177 Redundant Paths (边双连通分量)题解的更多相关文章

  1. poj3177 Redundant Paths 边双连通分量

    给一个无向图,问至少加入多少条边能够使图变成双连通图(随意两点之间至少有两条不同的路(边不同)). 图中的双连通分量不用管,所以缩点之后建新的无向无环图. 这样,题目问题等效于,把新图中度数为1的点相 ...

  2. POJ3177 Redundant Paths【双连通分量】

    题意: 有F个牧场,1<=F<=5000,现在一个牧群经常需要从一个牧场迁移到另一个牧场.奶牛们已经厌烦老是走同一条路,所以有必要再新修几条路,这样它们从一个牧场迁移到另一个牧场时总是可以 ...

  3. [POJ3177]Redundant Paths(双联通)

    在看了春晚小彩旗的E技能(旋转)后就一直在lol……额抽点时间撸一题吧…… Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Tota ...

  4. POJ3177 Redundant Paths —— 边双联通分量 + 缩点

    题目链接:http://poj.org/problem?id=3177 Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total ...

  5. [POJ3177]Redundant Paths(双连通图,割边,桥,重边)

    题目链接:http://poj.org/problem?id=3177 和上一题一样,只是有重边. 如何解决重边的问题? 1.  构造图G时把重边也考虑进来,然后在划分边双连通分量时先把桥删去,再划分 ...

  6. poj 3177 Redundant Paths(边双连通分量+缩点)

    链接:http://poj.org/problem?id=3177 题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任 ...

  7. [POJ3352]Road Construction

    [POJ3352]Road Construction 试题描述 It's almost summer time, and that means that it's almost summer cons ...

  8. POJ3352 Road Construction(边双连通分量)

                                                                                                         ...

  9. POJ3352 Road Construction (双连通分量)

    Road Construction Time Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Sub ...

随机推荐

  1. Ubuntu Kylin 14.04 安装配置 jdk、eclipse、tomcat 通用

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qq1053781225/article/details/24810107 一.安装jdk       ...

  2. android ImageView加圆角

    1.attrs添加 <declare-styleable name="RoundImageView"> <attr name="circle" ...

  3. gradle多工程依赖

    多工程依赖:http://blog.csdn.net/w8452960/article/details/53415415 https://www.cnblogs.com/softidea/p/4525 ...

  4. Scala里面如何使用枚举

    枚举通常用来定义已知数量的常量,比如月份,星期,季节等等,用过java的人都知道定义枚举的关键字是enum,在scala里面和java有所不同,来看一个完整的例子定义: object EnumTest ...

  5. [django]form不清空问题解决

    https://www.cnblogs.com/OldJack/p/7118396.html 有时候提交表单后,发现某个字段写错了,但是form的其他字段竟然被清空,这个万万不能接受.所有django ...

  6. [py][mx]django分页第三方模块django-pure-pagination

    前台的这些数据都是从后台取来的 分页模块django-pure-pagination - 一款基于django pagination封装的更好用的分页模块 https://github.com/jam ...

  7. 使用Python2.7 POST 数据到 onenet 平台

    功能 发送数据名称为SENSORID(这里用TEST测试),数值为VALUE(这里用49值做测试)的数据,发送到自己的onenet对应设备 效果发送成功 代码 # -*- coding: utf-8 ...

  8. data.frame和matrix的一些操作

    编写脚本的时候经常会涉及到对data.frame或matrix类型数据的操作,比如取指定列.取指定行.排除指定列或行.根据条件取满足条件的列或行等.在R中,这些操作都是可以通过简单的一条语句就能够实现 ...

  9. jquery更改表格行顺序实例

    使用jquery写的更改表格行顺序的小功能 表格部分: 复制代码代码如下: <table class="table" id="test_table"> ...

  10. linux 统计wc

    说明:该命令统计给定文件中的字节数.字数.行数.如果没有给出文件名,则从标准输入读取.wc同时也给出所有指定文件的总统计数.字是由空格字符区分开的最大字符串. 该命令各选项含义如下: - c 统计字节 ...