POJ 1523 SPF

次元传送门

题意:
本体就是对无向图求割点,并求删去割点后能把原图分成几个块
注意是多case,输入格式蛮恶心的,点的编号一定连续且从1开始,但原图可能不联通(用Tarjan的童鞋小心了!)

分析:
Tarjan求割点,删去点后DFS求块的数量,没啥技术含量

代码实现

#include<iostream>
#include<cstring> 
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1005,maxm=1000005;
int hd[maxn],nt[maxm],to[maxm],dfn[maxn],low[maxn],vis[maxn],v[maxn],cnt,tot,n,fnd,root,ans;
inline void reset(void){
    n=cnt=tot=fnd=0;
    memset(hd,-1,sizeof(hd));
    memset(dfn,0,sizeof(dfn));
    memset(vis,0,sizeof(vis));
}
inline void addedge(int x,int y){
    nt[cnt]=hd[x];
    to[cnt]=y;
    hd[x]=cnt++;
}
void Tarjan(int u){
    vis[u]=1,dfn[u]=low[u]=++tot;
    for(int i=hd[u];~i;i=nt[i])
        if(!vis[to[i]]) Tarjan(to[i]),low[u]=min(low[u],low[to[i]]),vis[u]+=low[to[i]]>=dfn[u];
        else low[u]=min(low[u],dfn[to[i]]);
    if(vis[u]>(1+(u==root)))    vis[u]=2,fnd++;
    else vis[u]=1;
}
int dfs(int u){
    v[u]=1;
    int ans=0;
    for(int i=hd[u];~i;i=nt[i])
        if(!v[to[i]])   ans++,dfs(to[i]);
    return ans;
}
int main(void){
    int x,y,c=0;
    do{
        reset();
        bool first=1;
        while(scanf("%d",&x)&&x)
            scanf("%d",&y),addedge(x,y),addedge(y,x),n=max(n,max(x,y)),first=0;
        if(first)   return 0;
        for(int i=1;i<=n;i++)
            if(!dfn[i]) root=i,Tarjan(i);
        printf("Network #%d\n",++c);
        if(!fnd)
            printf(" No SPF nodes\n");
        for(int i=1;i<=n;i++)
            if(vis[i]==2)   memset(v,0,sizeof(v)),printf(" SPF node %d leaves %d subnets\n",i,dfs(i));
        printf("\n");   
    }while(true);
    return 0;
}

By YOUSIKI

你可能感兴趣的:(POJ 1523 SPF)