poj3352 Road Construction & poj3177 Redundant Paths (边双连通分量)题解
题意:有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 (边双连通分量)题解的更多相关文章
- poj3177 Redundant Paths 边双连通分量
给一个无向图,问至少加入多少条边能够使图变成双连通图(随意两点之间至少有两条不同的路(边不同)). 图中的双连通分量不用管,所以缩点之后建新的无向无环图. 这样,题目问题等效于,把新图中度数为1的点相 ...
- POJ3177 Redundant Paths【双连通分量】
题意: 有F个牧场,1<=F<=5000,现在一个牧群经常需要从一个牧场迁移到另一个牧场.奶牛们已经厌烦老是走同一条路,所以有必要再新修几条路,这样它们从一个牧场迁移到另一个牧场时总是可以 ...
- [POJ3177]Redundant Paths(双联通)
在看了春晚小彩旗的E技能(旋转)后就一直在lol……额抽点时间撸一题吧…… Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Tota ...
- POJ3177 Redundant Paths —— 边双联通分量 + 缩点
题目链接:http://poj.org/problem?id=3177 Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total ...
- [POJ3177]Redundant Paths(双连通图,割边,桥,重边)
题目链接:http://poj.org/problem?id=3177 和上一题一样,只是有重边. 如何解决重边的问题? 1. 构造图G时把重边也考虑进来,然后在划分边双连通分量时先把桥删去,再划分 ...
- poj 3177 Redundant Paths(边双连通分量+缩点)
链接:http://poj.org/problem?id=3177 题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任 ...
- [POJ3352]Road Construction
[POJ3352]Road Construction 试题描述 It's almost summer time, and that means that it's almost summer cons ...
- POJ3352 Road Construction(边双连通分量)
...
- POJ3352 Road Construction (双连通分量)
Road Construction Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Sub ...
随机推荐
- Ubuntu Kylin 14.04 安装配置 jdk、eclipse、tomcat 通用
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qq1053781225/article/details/24810107 一.安装jdk ...
- android ImageView加圆角
1.attrs添加 <declare-styleable name="RoundImageView"> <attr name="circle" ...
- gradle多工程依赖
多工程依赖:http://blog.csdn.net/w8452960/article/details/53415415 https://www.cnblogs.com/softidea/p/4525 ...
- Scala里面如何使用枚举
枚举通常用来定义已知数量的常量,比如月份,星期,季节等等,用过java的人都知道定义枚举的关键字是enum,在scala里面和java有所不同,来看一个完整的例子定义: object EnumTest ...
- [django]form不清空问题解决
https://www.cnblogs.com/OldJack/p/7118396.html 有时候提交表单后,发现某个字段写错了,但是form的其他字段竟然被清空,这个万万不能接受.所有django ...
- [py][mx]django分页第三方模块django-pure-pagination
前台的这些数据都是从后台取来的 分页模块django-pure-pagination - 一款基于django pagination封装的更好用的分页模块 https://github.com/jam ...
- 使用Python2.7 POST 数据到 onenet 平台
功能 发送数据名称为SENSORID(这里用TEST测试),数值为VALUE(这里用49值做测试)的数据,发送到自己的onenet对应设备 效果发送成功 代码 # -*- coding: utf-8 ...
- data.frame和matrix的一些操作
编写脚本的时候经常会涉及到对data.frame或matrix类型数据的操作,比如取指定列.取指定行.排除指定列或行.根据条件取满足条件的列或行等.在R中,这些操作都是可以通过简单的一条语句就能够实现 ...
- jquery更改表格行顺序实例
使用jquery写的更改表格行顺序的小功能 表格部分: 复制代码代码如下: <table class="table" id="test_table"> ...
- linux 统计wc
说明:该命令统计给定文件中的字节数.字数.行数.如果没有给出文件名,则从标准输入读取.wc同时也给出所有指定文件的总统计数.字是由空格字符区分开的最大字符串. 该命令各选项含义如下: - c 统计字节 ...