重连通分量的求解

提两点:

1.对于每个点连通分量,都是根据割点来找的。

2.边入栈, 到当前边等于栈顶时停止出栈。

3.割点属于多个点连通分量。

邻接矩阵:

View Code
#include<stdio.h>
#include<string.h>
#define maxn 22
#define maxm 444
#define inf 1000000000

int min(int a, int b)
{
    return a < b ? a : b;
} 

int n, m;
bool map[maxn][maxn];
struct EE
{
    int u, v;
    void print()
    {
        printf("%d-%d", u, v);
    }
    bool cmp(EE &t)
    {
        return (t.u == u && t.v == v) || (t.u == v && t.v == u); 
    }
}e[maxm];
int top;

int dfn[maxn];
int low[maxn];
int id;
void dfs(int u)
{
    int i, v;
    EE t, tt;
    dfn[u] = low[u] = ++id;
    for(v = 1; v <= n; v++)
    {
        if(map[u][v])
        {
            t.u = u; t.v = v; e[++top] = t;
            map[v][u] = 0;// 避免边重复入栈。也排除了不回走的情况
            //当走过<u,v>后,不需要再走<v,u>,不走<v,u>不影响对割点的求解
            if(!dfn[v])
            {
                dfs(v);
                low[u] = min(low[u], low[v]);
                if(low[v] >= dfn[u]) // 割点的条件
                {
                    //可以打印,也可以保存
                    bool flag = 1;
                    while(1)
                    {
                        if(top == -1) break;
                        if(flag) flag = 0;
                        else printf(" ");
                        tt = e[top--];
                        tt.print();
                        if(tt.cmp(t)) break;
                    }
                    printf("\n");
                }
            }
            else low[u] = min(low[u], dfn[v]);
        }
    }
}

void init()
{
    memset(dfn, 0, sizeof(dfn));
    memset(map, 0, sizeof(map));
    top = -1;
    id = 0;
}

int main()
{
    int i, j;
    int x, y;
    while( ~scanf("%d%d", &n, &m))
    {
        init();
        while(m--)
        {
            scanf("%d%d", &x, &y);
            map[x][y] = map[y][x] = 1;
        }
        dfs(1);
    }
    return 0;
}
/*
7 9 
1 2
1 3
1 6
1 7
2 3
2 4
2 5
4 5
6 7
*/

 

邻接表:

View Code
#include<stdio.h>
#include<string.h>
#define maxn 22
#define maxm 444
#define inf 1000000000

int min(int a, int b)
{
    return a < b ? a : b;
} 

struct E
{
    int v, next, vis;
}edge[maxm];
int head[maxn], tot;
int n, m;

void add(int s, int t)
{
    edge[tot].v = t;
    edge[tot].vis = 1;
    edge[tot].next = head[s];
    head[s] = tot++;

    edge[tot].v = s;
    edge[tot].vis = 1;
    edge[tot].next = head[t];
    head[t] = tot++;
}
struct EE
{
    int u, v;
    void print()
    {
        printf("%d-%d", u, v);
    }
    bool cmp(EE &t)
    {
        return (t.u == u && t.v == v) || (t.u == v && t.v == u); 
    }
}e[maxm];
int top;

int dfn[maxn];
int low[maxn];
int id;
void dfs(int u, int fa)
{
    int i, v;
    EE t, tt;
    dfn[u] = low[u] = ++id;
    for(i = head[u]; i != -1; i = edge[i].next)
    {
        v = edge[i].v;
        if(edge[i].vis)
        {
            t.u = u; t.v = v; e[++top] = t;
            edge[i].vis =  edge[i^1].vis = 0;// 避免边重复入栈。
            if(!dfn[v])
            {
                dfs(v, u);
                low[u] = min(low[u], low[v]);
                if(low[v] >= dfn[u])
                {
                    bool flag = 1;
                    while(1)
                    {
                        if(top == -1) break;
                        if(flag) flag = 0;
                        else printf(" ");
                        tt = e[top--];
                        tt.print();
                        if(tt.cmp(t)) break;
                    }
                    printf("\n");
                }
            }
            else low[u] = min(low[u], dfn[v]);
        }
    }
}

void init()
{
    memset(dfn, 0, sizeof(dfn));
    memset(head, -1, sizeof(head));
    top = -1;    tot = 0;
    id = 0; 
}

int main()
{
    int i, j;
    int x, y;
    while( ~scanf("%d%d", &n, &m))
    {
        init();
        while(m--)
        {
            scanf("%d%d", &x, &y);
            add(x, y); 
        }
        dfs(1, -1);
    }
    return 0;
}
posted @ 2012-10-26 21:39  To be an ACMan  Views(379)  Comments(0)    收藏  举报