POJ 1523 SPF tarjan算法入门

注意:

对于生成树的每条边<u,v>:

u是割点的充要条件是:

1、若u为根节点, 它有2个以上包括两个的儿子(son >= 2)

2、u不为根节点,dfn[u] <= low[v];

View Code
#include<stdio.h>
#include<string.h>
#define maxn 1005
#define maxm maxn*maxn

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

struct E
{
    int v, next;
}edge[maxm<<1];

int tot, head[maxn];
int n;

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

    edge[tot].v = s;
    edge[tot].next = head[t];
    head[t] = tot++;
}

int low[maxn];
int sub[maxn]; // 去掉某个点后连通分量的个数
int dfn[maxn];
int id;
void dfs(int u, int fa) //加了fa只是减少了计算时间,去掉不影响AC
{
    int i, v;
    low[u] = dfn[u] = ++id;
    for(i = head[u]; i != -1; i = edge[i].next)
    {
        v = edge[i].v;
        if(v == fa) continue;
        if(!dfn[v])
        {
            dfs(v, u);
            low[u] = min(low[u], low[v]);
            if(low[v] >= dfn[u])
                    sub[u]++;
        }
        else low[u] = min(low[u], dfn[v]);
    }
}

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

int main()
{
    int i, j, x, y, cas = 1;
    while( ~scanf("%d", &x) && x)
    {
        init();
        scanf("%d", &y);
        add(x, y);
        n = max(n, max(x, y));
        while( ~scanf("%d", &x) && x)
        {
            scanf("%d", &y);
            n = max(n, max(x, y));
            add(x, y);
        }
        dfs(1, -1);
        printf("Network #%d\n", cas++);
        sub[1]--;  // 根节点特殊处理
        bool flag = 0;
        for(i = 1; i <= n; i++)
        {
            if(sub[i] >= 1)
            {
                printf("  SPF node %d leaves %d subnets\n", i, sub[i]+1);
                flag = 1;
            }
        }
        if(!flag) printf("  No SPF nodes\n");
        puts("");
    }
    return 0;
}

 

 

posted @ 2012-10-26 18:54  To be an ACMan  Views(257)  Comments(0)    收藏  举报