【POJ 1523】SPF(割点)

 儿子数大于1的树根或者 Low[v] >= DFN[u]的非树根节点v 就是割点。

#include <cstdio>
#include <cstring>

const int N = 1001;
const int M = 1000010;
struct Edge
{
    int to,next;
    bool cut;//是否为桥的标记
}edge[M];
int head[N],tot;
int Low[N],DFN[N],Stack[N];
int Index,top;
bool Instack[N];
bool cut[N];//是否为割点
int add_block[N];//删除一个点后增加的连通块
int bridge;
int va[N];
void addedge(int u,int v)
{
    edge[tot].to = v;edge[tot].next =head[u];edge[tot].cut = false;
    head[u] = tot++;
}
void Tarjan(int u,int pre)
{
    int v;
    Low[u] = DFN[u] = ++Index;
    Stack[top++] = u;
    Instack[u] = true;
    int son = 0;
    for(int i = head[u];~i;i = edge[i].next)
    {
        v = edge[i].to;
        if(v == pre)continue;
        if( !DFN[v] )
        {
            son++;
            Tarjan(v,u);
            if(Low[u] > Low[v])Low[u] = Low[v];
            //
            if(Low[v] > DFN[u])
            {
                bridge++;
                edge[i].cut = true;
                edge[i^1].cut = true;
            }
            if(u != pre && Low[v] >= DFN[u])//不是树根
            {
                cut[u] = true;
                add_block[u]++;
            }
        }
        else if( Low[u] > DFN[v])
            Low[u] = DFN[v];
    }
    //树根,分支数大于1
    if(u == pre && son > 1)cut[u] = true;
    if(u == pre)add_block[u] = son - 1;
    Instack[u] = false;
    top--;
}
void solve(){
    memset(DFN,0,sizeof DFN);
    memset(Instack,0,sizeof Instack);
    memset(add_block,0,sizeof add_block);
    memset(cut,false,sizeof cut);
    Index=top=0;
    int cnt=0,ans=0;
    for(int i=1;i<N;i++)
        if(va[i]&&!DFN[i]){
            Tarjan(i, i);
            cnt++;
        }
    for(int i=1;i<N;i++)
        if(cut[i]){
            ans++;
            printf("  SPF node %d leaves %d subnets
",i,cnt+add_block[i]);
        }
    if(ans==0)
        puts("  No SPF nodes");
    
}
void init(){
    memset(head,-1,sizeof head);
    memset(va,0,sizeof va);
    tot=0;
}
int main(){
    int u,v,cas=0;
    init();
    while(~scanf("%d",&u)){
        if(u==0&&tot){
            printf("Network #%d
",++cas);
            solve();
            init();
            puts("");
            continue;
        }
        scanf("%d",&v);
        addedge(u,v);
        addedge(v,u);
        va[u]=va[v]=1;
    }
}

  

原文地址:https://www.cnblogs.com/flipped/p/5759362.html