Redundant Paths-POJ3177(并查集+双连通分量)
Description
path and want to build some new paths so that they will always have a choice of at least two separate routes between any pair of fields. They currently have at least one route between each pair of fields and want to have at least two. Of course, they can only
travel on Official Paths when they move from one field to another.
Given a description of the current set of R (F-1 <= R <= 10,000) paths that each connect exactly two different fields, determine the minimum number of new paths (each of which connects exactly two fields) that must be built so that there are at least two separate
routes between any pair of fields. Routes are considered separate if they use none of the same paths, even if they visit the same intermediate field along the way.
There might already be more than one paths between the same pair of fields, and you may also build a new path that connects the same fields as some other path.
Input
Lines 2..R+1: Each line contains two space-separated integers which are the fields at the endpoints of some path.
Output
Sample Input
7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7
Sample Output
2
Hint
One visualization of the paths is:
1 2 3
+---+---+
| |
| |
6 +---+---+ 4
/ 5
/
/
7 +
Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions.
1 2 3
+---+---+
: | |
: | |
6 +---+---+ 4
/ 5 :
/ :
/ :
7 + - - - -
Check some of the routes:
1 – 2: 1 –> 2 and 1 –> 6 –> 5 –> 2
1 – 4: 1 –> 2 –> 3 –> 4 and 1 –> 6 –> 5 –> 4
3 – 7: 3 –> 4 –> 7 and 3 –> 2 –> 5 –> 7
Every pair of fields is, in fact, connected by two routes.
It's possible that adding some other path will also solve the problem (like one from 6 to 7). Adding two paths, however, is the minimum.
Source
给定一个无向连通图,判断至少加多少的边,才能使任意两点之间至少有两条的独立的路(没有公共的边,但可以经过同一个中间的顶点)。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define LL long long using namespace std; const int MaxN = 10100; const int MaxM = 5100;
// 建图
typedef struct node
{
int v;
int next;
}Line; Line Li[MaxN*2]; int Belong[MaxM];//判断所属的双连通的集合
//回到最优先遍历度最小的节点和记录点DFS的顺序
int low[MaxM],dfn[MaxM]; int Head[MaxM],top; int pre[MaxM]; //并查集 int vis[MaxM],Num;//标记点的状态 int Bridge[MaxM][2],NumB;//记录图中的桥 void AddEdge(int u,int v)// 建边
{
Li[top].v=v; Li[top].next=Head[u];
Head[u]=top++; Li[top].v=u; Li[top].next=Head[v];
Head[v]=top++;
} int Find(int x)// 路径压缩
{
return pre[x]==-1?x:pre[x]=Find(pre[x]);
} void Union(int x,int y)
{
int Fx = Find(x); int Fy = Find(y); if(Fx!=Fy)
{
pre[Fx] = Fy;
}
} void dfs(int u,int father)
{
low[u]=dfn[u]=Num++; vis[u]=1;//表示已经遍历但是没有遍历完子女 for(int i=Head[u];i!=-1;i=Li[i].next)
{
int j=Li[i].v; if(vis[j]==1&&j!=father)// 回到的祖先
{
low[u]=min(low[u],dfn[j]);
}
if(vis[j]==0)
{
dfs(j,u); low[u]=min(low[j],low[u]); if(low[j]<=dfn[u])//说明是双连分量中的边
{
Union(u,j);
}
if(low[j]>dfn[u])//桥
{
Bridge[NumB][0]=j;
Bridge[NumB++][1]=u;
}
}
}
vis[u]=2;
} int main()
{
int n,m; while(~scanf("%d %d",&n,&m))
{ top=0; int u,v; memset(Head,-1,sizeof(Head)); memset(pre,-1,sizeof(pre));
for(int i=1;i<=m;i++)
{
scanf("%d %d",&u,&v); AddEdge(u,v);
} memset(vis,0,sizeof(vis)); memset(Belong ,-1 ,sizeof(Belong)); Num = 0 ; NumB=0 ; dfs(1,0); Num = 0;
for(int i=1;i<=n;i++)
{
int k=Find(i);//给双连通分量集合编号 if(Belong[k]==-1)
{
Belong[k]=++Num;
}
Belong[i]=Belong[k];
}
memset(vis,0,sizeof(vis)); for(int k=0;k<NumB;k++)
{
int i=Bridge[k][0]; int j=Bridge[k][1]; vis[Belong[i]]++; vis[Belong[j]]++;
} int ans = 0; for(int i=1;i<=n;i++)
{
if(vis[i]==1)
{
ans++;
}
}
printf("%d\n",(ans+1)/2);
}
return 0;
}
Redundant Paths-POJ3177(并查集+双连通分量)的更多相关文章
- POJ3177:Redundant Paths(并查集+桥)
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 19316 Accepted: 8003 ...
- Redundant Paths POJ - 3177(边—双连通分量)
题意: 在图中加边 看最少能通过加多少条边把 图变成边—双连通分量 解析: 先做一次dfs,不同的连通分量的low是不同的 注意重边 缩点 统计度为1的点 那么需要加的边为(ret+1)/2 #i ...
- poj-3177(并查集+双联通分量+Tarjan算法)
题目链接:传送门 思路: 题目要将使每一对草场之间都有至少两条相互分离的路径,所以转化为(一个有桥的连通图至少加几条边才能变为双联通图?) 先求出所有的桥的个数,同时将不同区块收缩成一个点(利用并查集 ...
- HDU - 5438 Ponds(拓扑排序删点+并查集判断连通分量)
题目: 给出一个无向图,将图中度数小于等于1的点删掉,并删掉与他相连的点,直到不能在删为止,然后判断图中的各个连通分量,如果这个连通分量里边的点的个数是奇数,就把这些点的权值求和. 思路: 先用拓扑排 ...
- [HDU1232] 畅通工程 (并查集 or 连通分量)
Input 测试输入包含若干测试用例.每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M:随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的 ...
- poj3177重修道路——边双连通分量缩点
题目:http://poj.org/problem?id=3177 找桥,缩点,总之都是板子: 对于每个叶子,互相连一条边即可:若最后剩下一个,则去和根节点连边: 所以叶子节点数+1再/2即答案. 代 ...
- PAT Advanced A1021 Deepest Root (25) [图的遍历,DFS,计算连通分量的个数,BFS,并查集]
题目 A graph which is connected and acyclic can be considered a tree. The height of the tree depends o ...
- POJ2985 The k-th Largest Group[树状数组求第k大值+并查集||treap+并查集]
The k-th Largest Group Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 8807 Accepted ...
- 并查集(UVA 1106)
POINT: 把每个元素看成顶点,则一个简单化合物就是一条无向边,若存在环(即k对组合中有k种元素),则危险,不应该装箱,反之,装箱: 用一个并查集维护连通分量集合,每次得到一种化合物(x, y)时检 ...
随机推荐
- backbone学习笔记一
backbone是一个MVC单页面框架,针对传统的WEB开发B/S架构的缺点,即通过表现层的浏览器,功能层的WEB服务器,数据层的数据库服务器构架,而操作渲染过程太过复杂.
- super()和this()的区别
1)调用super()必须写在子类构造方法的第一行,否则编译不通过.每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错. 2)supe ...
- Struts和SpringMVC两种MVC框架比较
基于Web的MVC framework在J2EE的世界内已是空前繁荣.TTS网站上几乎每隔一两个星期就会有新的MVC框架发布.目前比较好的MVC,老牌的有Struts.Webwork.新兴的MVC框架 ...
- 类似input框内最右边添加图标,有清空功能
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- bootstrap日期插件
<!DOCTYPE HTML> <html> <head> <link href="http://netdna.bootstrapcdn.com/t ...
- 《JAVA开发环境的熟悉》实验报告——20145337
- NFS服务器搭建
1. 安装nfs-kernel-server,然后编辑/etc/exports. /sambadata/nfsserver 10.0.0.0/255.255.255.0(fsid=0,all_s ...
- 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...
- apple mobile device服务无法启动,错误1053 解决
我不想安装iTunes,于是下了iTunes64安装包,解压后得到6个文件 安装完 AppleMobileDeviceSupport64.msi 发现服务启动不起来,提示错误1053,网上搜了下发现出 ...
- Shell displays color output
格式: echo "/033[字背景颜色;字体颜色m字符串/033[控制码" 如果单纯显示字体颜色可以固定控制码位0m. 格式: echo "/033[字背景颜色;字体颜 ...