POJ1523:SPF——题解

http://poj.org/problem?id=1523

这题明显就是求割点然后求割完之后的强连通分量的个数。

割点都会求,怎么求割完的分量个数呢?

我们可以通过万能的并查集啊!(具体做法看代码吧,方法不好叙述)

这样我们查割点它所连的点一共隶属于几个集合即可。

(PS:读入方式很恶心,同时请注意快速读入)

#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
inline int read(){
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*w;
}
const int maxn=1001;
bool dis[maxn][maxn];
bool cut[20001];
int dfn[maxn];
int low[maxn];
int fa[maxn];
int from[maxn];
int t;
int big[maxn];
int to[maxn];
int find(int a){
    if(a==fa[a])return a;
    return fa[a]=find(fa[a]);
}
void tarjan(int u,int f){
    bool tong[maxn]={0};
    from[u]=f;
    t++;
    dfn[u]=t;
    low[u]=t;
    to[t]=u;
    for(int v=1;v<=maxn;v++){
    if(dis[u][v]){
        if(!dfn[v]){
        tarjan(v,u);
        low[u]=min(low[u],low[v]);
        }else if(f!=v){
        low[u]=min(low[u],dfn[v]);
        }
    }
    fa[find(u)]=find(to[low[u]]);
    }
    for(int v=1;v<=maxn;v++){
    if(dis[u][v]){
        if(!tong[find(v)]){
        tong[find(v)]=1;
        big[u]++;
        }
    }
    }
    return;
}
int main(){
    int u,v;
    int cnt=0;
    bool smg=0;
    while(233){
    int u=read();
    if(!u&&!smg)break;
    smg=1;
    if(!u){
        for(int i=1;i<=maxn;i++)fa[i]=i;
        tarjan(1,0);
        int rootson=0;
        bool ok=0;
        for(int i=2;i<=maxn;i++){
        int v=from[i];
        if(v==1)rootson++;
        else{
            if(low[i]>=dfn[v]&&low[i]&&dfn[i]){
            cut[v]=1;
            ok=1;
            }
        }
        }
        if(rootson>=2){
        cut[1]=1;
        ok=1;
        }
        cnt++;
        printf("Network #%d
",cnt);
        if(ok==0){
        printf("  No SPF nodes
");
        }else{
        for(int i=1;i<=maxn;i++){
            if(cut[i])printf("  SPF node %d leaves %d subnets
",i,big[i]);
        }
        }
        printf("
");
        memset(cut,0,sizeof(cut));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(fa,0,sizeof(fa));
        memset(from,0,sizeof(from));
        memset(dis,0,sizeof(dis));
        memset(big,0,sizeof(big));
        memset(to,0,sizeof(to));
        t=0;
        smg=0;
        continue;
    }
    int v=read();
    dis[u][v]=dis[v][u]=1;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/luyouqi233/p/7845890.html