[割点] poj 1523 SPF

来源:互联网 发布:mac没有管理员账户 编辑:程序博客网 时间:2024/05/01 11:24
/**[割点] poj 1523 SPF求割点及去掉该割点后的连通分量个数。dfn[] dfs产生的优先数low[u] 从u或u的子孙出发通过回边可以到达的最低深度优先数low[u] = min{dfn[u], min{low[w]|w是u的一个子女}, min{dfn[v]|v与u邻接且(u,v)是一条回边} }顶点u是割点的充要条件是: u 或者 是具有两个以上子女的深度优先生成树的根,或者虽不是一个根,但他有一个子女w使得low[w] >= dfn[u]*/#include <stdio.h>#include <string.h>#include <vector>#include <algorithm>using namespace std;#define N 1001vector<int> vec[N];int low[N],dfn[N],subnet[N],vis[N];int cnt,son,n;void dfs(int u){    for(int i = 0; i < vec[u].size(); ++i)    {        int v = vec[u][i];        if(!vis[v])        {            vis[v] = 1;            low[v] = dfn[v] = ++cnt;            dfs(v);            low[u] = min(low[v],low[u]);            if(low[v] >=dfn[u])            {                if(u == n)                    ++son;                else                    ++subnet[u];            }        }        else            low[u] = min(low[u],dfn[v]);    }}void cutPoint(){    memset(subnet,0,sizeof(subnet));    memset(vis,0,sizeof(vis));    dfn[n] = low[n] = vis[n] = 1;    cnt = 1;    son = 0;    dfs(n);    if(son > 1)        subnet[n] = son - 1;    //if subnet[i] != 0 则i为割点且删除i后的连通分量个数为subnet[i] + 1    for(int i = 1; i <= n; ++i)        vec[i].clear();}int main(){    int a,b,cas = 0;    while(scanf("%d",&a) && a)    {        n = a;        scanf("%d",&b);        n = max(n,b);        vec[a].push_back(b);        vec[b].push_back(a);        while(scanf("%d",&a) && a)        {            scanf("%d",&b);            n = max(a,n);            n = max(b,n);            vec[a].push_back(b);            vec[b].push_back(a);        }        cutPoint();        printf("Network #%d\n",++cas);        int i,find = 0;        for(i = 1; i <= n; ++i)            if(subnet[i])            {                find = 1;                printf("  SPF node %d leaves %d subnets\n",i,subnet[i] + 1);            }        if(!find)            printf("  No SPF nodes\n");        puts("");    }    return 0;}