Network of Schools POJ - 1236 Java

先做一次裸tarjan,题目的思想主要是: 把一个SCC(强连通)看作一个点(缩点), 我们统计一下,每个SCC 的 入度和出度,因而再统计入度为零和出度为零的个数。 最后的两个答案, 是 入度为零的个数 和 max(入度为零,出度为零)。

import java.io.BufferedInputStream;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;

public class poj1236{
	static int[]in,belong,out,ins,head,low,dfn;
	static int n,m,con,ans,cnt,time;
	static   Stack<Integer> s;
	static class e{
		int u,v;int next;
	}static e[]es;
	static void add(int u,int v) {
		if(es[con]==null) es[con]=new e();
		es[con].v=v;	es[con].next=head[u];head[u]=con++;
	}
	static void tarjan(int u) {
		 s.add(u); ins[u]=1; dfn[u]=low[u]=++time;
		 for(int i=head[u];i!=-1; i=es[i].next) {
			 int v= es[i].v;
			 if(dfn[v]==0) { tarjan(v);  low[u]= Math.min(low[v] ,low[u]);  }
			 else if(ins[v]==1) low[u]= Math.min(dfn[v], low[u]);
		 }
		 if(dfn[u]==low[u]) {
			 ans++; 
			 int j = -1;
			  while(j!=u && !s.isEmpty()) {
				  j=s.pop(); ins[j]=0; belong[j]=ans; 
			  }
		 }
	}
	public static void main(String[] args) {
		Scanner sc= new Scanner(new BufferedInputStream(System.in));
		es=new e[10005];
		head=new int[ 10005];
		low=new int[200];
		dfn=new int[200];
		belong=new int[200];
		ins =new int[200];
		in=new int[200];
		out=new int[200];
		s=new Stack<Integer>(); s.clear();
		Arrays.fill(head,-1); con=0; time=0;ans=0;
		Arrays.fill(dfn,0);
		Arrays.fill(ins,0);
		Arrays.fill(in,0);
		Arrays.fill(out,0);
		Arrays.fill(low,0);
		Arrays.fill(belong,0);
		int m =sc.nextInt();
		for(int i=1;i<=m;i++) {
			while(sc.hasNext()) {
				int a=sc.nextInt();
				if(a==0) break;
				else {
					add(i,a);
				}
			}
		}
		 for(int i=1;i<=m;i++) {
			 if(dfn[i]==0) {
				 tarjan(i);
			 }
		 }
		 for(int i=1;i<=m;i++) {
			 for(int j=head[i];  j!=-1; j=es[j].next) {
				 int v =es[j].v;
				 if(belong[i]!=belong[v]) {
					 out[belong[i]]++;
					 in[belong[v]]++;
				 }
			 }
		 }
		 int  outnum=0,innum=0;  //出度为零的Scc 的数量 , 入度为零的scc的数量
		 for(int i=1;i<=ans;i++) {
			  if(in[i]==0) innum++;
			  if(out[i]==0)outnum++;
		 }
		 System.out.println( innum); 
		  if(ans==1)System.out.println( 0);
		  else System.out.println(Math.max( innum,outnum));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值