POJ1523 SPF 无向图求割点

简单的无向图求割点.

代码如下:

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAXN 1005
using namespace std;

int head[MAXN], idx, LIM, dfn[MAXN], low[MAXN], ti;
int subnet[MAXN];
bool vis[MAXN];

struct Edge
{
    int v, next;    
}e[MAXN*MAXN];

void AddEdge(int x, int v)
{
    ++idx;
    e[idx].v = v, e[idx].next = head[x];
    head[x] = idx;    
}

void dfs(int u)
{ // low 值一定是越低越好
    for (int i = head[u]; i != -1; i = e[i].next) {
        if (!vis[e[i].v]) {
            vis[e[i].v] = true;
            dfn[e[i].v] = low[e[i].v] = ++ti;
            dfs(e[i].v); 
            low[u] = min(low[u], low[e[i].v]);
            if (low[e[i].v] == dfn[u]) { // 孩子中不存在抵达上层的其他途径  
                ++subnet[u];
            }
        }
        else {
            low[u] = min(low[u], dfn[e[i].v]);
        }
    }
}

void solve()
{
    bool flag = false;
    memset(vis, false, sizeof (vis));
    memset(subnet, 0, sizeof (subnet));
    subnet[1] = -1;
    vis[1] = true; // 由于图一定是联通的,所以就一定能够找到所有的点
    dfn[1] = low[1] = ++ti;
    dfs(1);
    for (int i = 1; i <= LIM; ++i) {
        if (subnet[i] > 0) {
            printf("  SPF node %d leaves %d subnets\n", i, subnet[i]+1);
            flag = 1;
        }
    }
    if (!flag) {
        puts("  No SPF nodes");    
    }
}

int main()
{
    int a, b, ca = 0;
    bool indata = false, first = true;
    LIM = ti = 0, idx = -1;
    memset(head, 0xff, sizeof (head));
    while (1) {
        scanf("%d", &a);
        LIM = max(LIM, a);
        if (!a) {
            if (!indata) break;
            else {
                if (first) {
                    first = false;    
                }
                else {
                    puts("");
                }
                indata = false;
                printf("Network #%d\n", ++ca);
                solve();
                LIM = ti = 0, idx = -1; // 一个初始化
                memset(head, 0xff, sizeof (head));
                continue;
            }
        }
        indata = true;
        scanf("%d", &b);  // 表示a,b之间有一条无向边
        LIM = max(LIM, b); // 找到最大的顶点编号
        AddEdge(a, b);
        AddEdge(b, a);  // 无向图的双向边 
    }
    return 0;    
}
原文地址:https://www.cnblogs.com/Lyush/p/2647257.html