poj 3694 中等难度的双…
2013-12-14 20:05
363 查看
题意:给出一个连通图 , 并且给出Q条边 , 问每添加一条边之后 , 图中还剩下多少条桥?
解法:我们先把原图中的所有边-双连通分量 , 全部都缩成一个点 , 那么形成的一个新图就是一颗树了 ,
在新图中任意两个点之间只有一条路径(边不重复) , 每当我们添加一条新的边的时候 , 我们就用dfs来找到这条路径 ,
并且标记着条路径, 那么就等于这条路径上的所有边都不再是桥了 , 我们用总的桥的数量 , 减去这条路径上没有被标记的边的数量 ,
这就是添加了这条边之后 , 剩下的桥。
注意:原图中有重边
代码:
#include
#include
#include
#include
using namespace std;
#define maxn 100010
int low[maxn] , pre[maxn] , is_cnt[maxn] , sum;
int n , dfs_clock , m , edge_sum;
struct node
{
int u
;
int
next;
bool
select;
}edge[400010];
int head[maxn];
int p[maxn] , grap[maxn][2];
void init()
{
memset(head
, -1, sizeof(head));
memset(pre ,
0 , sizeof(pre));
for(int i =
1; i <= n; i++)
p[i] =
i;
dfs_clock =
0;
sum =
0;
edge_sum =
0;
}
int find(int x)
{
int g = x ,
h;
while(x !=
p[x]) x = p[x];
while(p[g]
!= x)
{
h =
p[g];
p[g] =
x;
g = h;
}
return
x;
}
void Union(int x , int y)
{
int g =
find(x) , h = find(y);
if(g !=
h) p[g] = h;
}
int dfs(int u)
{
//
cout<<u<<endl;
int lowu =
low[u] = ++dfs_clock;
int i , lowv
, child = 0;
for(i =
head[u] ; i != -1; i = edge[i].next)
{
int v =
edge[i].u;
if(!edge[i].select)
{
edge[i].select = true;//这里就能判断重边
edge[i^1].select = true;
if(!pre[v])
{
child +=
1;
pre[v] =
1;
lowv =
dfs(v);
lowu =
min(lowu , lowv);
if(lowv >
low[u])
grap[edge_sum][0] = u , grap[edge_sum++][1] = v;
解法:我们先把原图中的所有边-双连通分量 , 全部都缩成一个点 , 那么形成的一个新图就是一颗树了 ,
在新图中任意两个点之间只有一条路径(边不重复) , 每当我们添加一条新的边的时候 , 我们就用dfs来找到这条路径 ,
并且标记着条路径, 那么就等于这条路径上的所有边都不再是桥了 , 我们用总的桥的数量 , 减去这条路径上没有被标记的边的数量 ,
这就是添加了这条边之后 , 剩下的桥。
注意:原图中有重边
代码:
#include
#include
#include
#include
using namespace std;
#define maxn 100010
int low[maxn] , pre[maxn] , is_cnt[maxn] , sum;
int n , dfs_clock , m , edge_sum;
struct node
{
int u
;
int
next;
bool
select;
}edge[400010];
int head[maxn];
int p[maxn] , grap[maxn][2];
void init()
{
memset(head
, -1, sizeof(head));
memset(pre ,
0 , sizeof(pre));
for(int i =
1; i <= n; i++)
p[i] =
i;
dfs_clock =
0;
sum =
0;
edge_sum =
0;
}
int find(int x)
{
int g = x ,
h;
while(x !=
p[x]) x = p[x];
while(p[g]
!= x)
{
h =
p[g];
p[g] =
x;
g = h;
}
return
x;
}
void Union(int x , int y)
{
int g =
find(x) , h = find(y);
if(g !=
h) p[g] = h;
}
int dfs(int u)
{
//
cout<<u<<endl;
int lowu =
low[u] = ++dfs_clock;
int i , lowv
, child = 0;
for(i =
head[u] ; i != -1; i = edge[i].next)
{
int v =
edge[i].u;
if(!edge[i].select)
{
edge[i].select = true;//这里就能判断重边
edge[i^1].select = true;
if(!pre[v])
{
child +=
1;
pre[v] =
1;
lowv =
dfs(v);
lowu =
min(lowu , lowv);
if(lowv >
low[u])
grap[edge_sum][0] = u , grap[edge_sum++][1] = v;
相关文章推荐
- poj 3177 有点难度的边-双连通
- zoj 2588 简单的双连通分量
- poj 1144 求图的割点
- poj 1386 欧拉图的应用
- poj 1300 简单的欧拉图…
- 女眞關係
- poj 3159 差分约束+最短…
- poj 2983 中等的差分约束
- zoj 2770 差分约束的应用及其原理
- poj 1734 Floyd算求有向图的最小环
- poj 2570 floyd算法+二进制的应用
- poj 3249 DAG上的最短路问题
- poj 2449 求第k最短路 A* + SPFA
- poj 2253 dijkstra
- poj 1125 简单的floyd应…
- poj 3268 简单的SPFA算法运用
- poj 2387 简单的dijkstra运用
- poj 1135 有点弯的最短路运用
- poj 1079 判断最…
- poj 1258 简单的prim算法运用