您的位置:首页 > 其它

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;

   
   
  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: