POJ 1523

Tarjan找割点,分成的部分就是该点的子树个数加1(根要特判)

输入输出方式好恶心呀。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#define N  11000
using namespace std;
int to[N*10],cnt,nxt[N*10],head[N],vis[N],low[N],dfn[N],now;
int ans,z[N],top,n,m,in[N],k,rt[N],p[N],flag,d[N];
void add(int x,int y){
  to[++cnt]=y;
  nxt[cnt]=head[x];
  head[x]=cnt;
}
void dfs(int x){
  vis[x]=1;dfn[x]=low[x]=++now;
  z[++top]=x;in[x]=1;
  for(int i=head[x];i;i=nxt[i]){
    if(vis[to[i]]){
      if(in[to[i]]) low[x]=min(low[x],dfn[to[i]]);
    }else {
      dfs(to[i]);if(dfn[x]<=low[to[i]])p[x]=1,d[x]++;
      low[x]=min(low[x],low[to[i]]);
    }
  }
}
int main(){
  int x,y;
  for(int c=1;;c++){
    flag=cnt=top=0;
    memset(vis,0,sizeof(vis));
    memset(z,0,sizeof(z));
    memset(d,0,sizeof(d));
    memset(p,0,sizeof(p));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    memset(head,0,sizeof(head));
    memset(rt,0,sizeof(rt));
    for(k=1,n=0;;k++){
      scanf("%d",&x);
      if(k==1&&x==0) return 0;
      if(x==0) break;
      scanf("%d",&y);
      add(x,y);
      add(y,x);
      n=max(max(x,y),n);
    }printf("Network #%d ",c);
    for(int i=1;i<=n;i++) if(!vis[i]) rt[i]=1,dfs(i);
    for(int i=1;i<=n;i++) if(p[i]&&d[i]-rt[i]>0) printf("  SPF node %d leaves %d subnets ",i,d[i]-rt[i]+1),flag=1;
    if(!flag) printf("  No SPF nodes ");
    printf(" ");
  }
  for(int i=1;i<=n;i++) if(!vis[i])
              dfs(i);
  printf("%d",ans);
}

原文地址:https://www.cnblogs.com/blogoflyn/p/10888297.html