ZOJ 2588 Burning Bridges

 

大意:求一个无向图的割边,其中可能有重边。

思路:Tarjan求保存割边,排序输出。

不知咋的,数组开到题目给定的100010会报错,改成200020就行了,KD啊。

CODE:

 

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
using  namespace std;

#define MAXN 10010
#define MAXM 100010

struct Edge
{
     int v, next;
     int id;
}edge[MAXM*2];

int first[MAXN], low[MAXN], dfn[MAXN];
int bridge[MAXM*2];

int n, m;
int cnt;
int tot, nbridge;

void init()
{
    cnt =  0;
    tot = nbridge =  0;
    memset(first, - 1sizeof(first));
    memset(dfn,  0sizeof(dfn));
}

void read_graph( int u,  int v,  int id)
{
    edge[cnt].v = v, edge[cnt].id = id;
    edge[cnt].next = first[u], first[u] = cnt++;
}

int check( int u,  int fa)
{
     int count =  0;
     for( int e = first[u]; e != - 1; e = edge[e].next)
    {
         int v = edge[e].v;
         if(v == fa) count++;
    }
     if(count >=  2return  1;
     return  0;
}

void read_graph2()
{
    scanf( " %d%d ", &n, &m);
     for( int i =  1; i <= m; i++)
    {
         int u, v;
        scanf( " %d%d ", &u, &v);
        read_graph(u, v, i);
        read_graph(v, u, i);
    }
}

void Tarjan( int u,  int fa)
{
    dfn[u] = low[u] = ++tot;
     bool repeat =  0;
     for( int e = first[u]; e !=-  1; e = edge[e].next)
    {
         int v = edge[e].v;
         if(v == fa && !repeat)  // 去掉一条反向边,其余的可能是重边。 
        {
            repeat =  1;
             continue;
        }
         if(!dfn[v])
        {
            Tarjan(v, u);
            low[u] = min(low[u], low[v]);
             if(dfn[u] < low[v])    bridge[nbridge++] = edge[e].id;
        }    //if(dfn[u] <= low[v]) 求割顶
        low[u] = min(low[u], dfn[v]);
    }
}

void solve()
{
    Tarjan( 1, - 1);
    sort(bridge, bridge+nbridge);
    printf( " %d\n ", nbridge);
     for( int i =  0; i < nbridge; i++)    printf(i != nbridge- 1" %d  ": " %d\n ", bridge[i]);
}

int main()
{
     int T;
    scanf( " %d ", &T);
     while(T--)
    {
        init();
        read_graph2();
        solve();
         if(T) printf( " \n "); 
    }
     return  0;
}

 

判重方法2:

 

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
using  namespace std;

#define MAXN 10010
#define MAXM 100010

struct Edge
{
     int v, next;
     int id;
}edge[MAXM*2];

int first[MAXN], low[MAXN], dfn[MAXN];
int bridge[MAXM*2];

int n, m;
int cnt;
int tot, nbridge;

void init()
{
    cnt =  0;
    tot = nbridge =  0;
    memset(first, - 1sizeof(first));
    memset(dfn,  0sizeof(dfn));
}

void read_graph( int u,  int v,  int id)
{
    edge[cnt].v = v, edge[cnt].id = id;
    edge[cnt].next = first[u], first[u] = cnt++;
}

int check( int u,  int fa)
{
     int count =  0;
     for( int e = first[u]; e != - 1; e = edge[e].next)
    {
         int v = edge[e].v;
         if(v == fa) count++;
    }
     if(count >=  2return  1;
     return  0;
}

void read_graph2()
{
    scanf( " %d%d ", &n, &m);
     for( int i =  1; i <= m; i++)
    {
         int u, v;
        scanf( " %d%d ", &u, &v);
        read_graph(u, v, i);
        read_graph(v, u, i);
    }
}

void Tarjan( int u,  int fa)
{
    dfn[u] = low[u] = ++tot;
     bool repeat =  0;
     for( int e = first[u]; e !=-  1; e = edge[e].next)
    {
         int v = edge[e].v;
         if(v == fa && !repeat)  // 去掉一条反向边,其余的可能是重边。 
        {
            repeat =  1;
             continue;
        }
         if(!dfn[v])
        {
            Tarjan(v, u);
            low[u] = min(low[u], low[v]);
             if(low[v] > dfn[u])    bridge[nbridge++] = edge[e].id;
        }
        low[u] = min(low[u], dfn[v]);
    }
}

void solve()
{
    Tarjan( 1, - 1);
    sort(bridge, bridge+nbridge);
    printf( " %d\n ", nbridge);
     for( int i =  0; i < nbridge; i++)    printf(i != nbridge- 1" %d  ": " %d\n ", bridge[i]);
}

int main()
{
     int T;
    scanf( " %d ", &T);
     while(T--)
    {
        init();
        read_graph2();
        solve();
         if(T) printf( " \n "); 
    }
     return  0;
}

 

你可能感兴趣的:(bridge)