POJ 2186 强连通缩点



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) {
		new POJ2186().solve();
	}
}

class POJ2186 implements Define{

	InputReader in = new InputReader(System.in);
	PrintWriter out = new PrintWriter(System.out);
    
	Tarjan tarjan = new Tarjan() ;

	void solve() {

		int n = in.nextInt();
		int m = in.nextInt();
		tarjan.clear();
		
		while (m-- > 0) {
			tarjan.add(in.nextInt(), in.nextInt());
		}
		
		out.println(tarjan.doTarjan(n)) ;
		out.flush();
	}

}


class Tarjan implements Define{

	class Edge {
		int u, v, next;
		boolean sign;

		Edge(int u, int v, boolean sign, int next) {
			this.u = u;
			this.v = v;
			this.sign = sign;
			this.next = next;
		}
	}

	Edge[] e = new Edge[M];
	int[] head = new int[N];
	int eid;

	void add(int u, int v) {
		e[eid] = new Edge(u, v, false, head[u]);
		head[u] = eid++;
	}

	int[] dfn = new int[N];
	int[] low = new int[N];
	int[] stack = new int[N];
	boolean[] inStack = new boolean[N];
	int[] belong = new int[N];
	int[] bccSize = new int[N];
	int top, dfnTime, bccId;

	void tarjan(int u, int father) {
		dfn[u] = low[u] = ++dfnTime;
		stack[top++] = u;
		inStack[u] = true;
		for (int i = head[u]; i != -1; i = e[i].next) {
			int v = e[i].v;
			if (dfn[v] == -1) {
				tarjan(v, u);
				low[u] = Math.min(low[u], low[v]);
				if (dfn[u] < low[v])
					e[i].sign = true;
			} else if (inStack[v])
				low[u] = Math.min(low[u], dfn[v]);
		}
		if (low[u] == dfn[u]) {
			int now;
			bccId++;
			do {
				now = stack[--top];
				inStack[now] = false;
				belong[now] = bccId;
				bccSize[bccId]++;
			} while (now != u);
		}
	}

	void clear() {
		Arrays.fill(dfn, -1);
		Arrays.fill(head, -1);
		Arrays.fill(inStack, false);
		Arrays.fill(bccSize, 0);
		eid = top = dfnTime = bccId = 0;
	}
	
	int[] outDegree = new int[N] ;
	
	int doTarjan(int n){
		for (int i = 1; i <= n; i++) {
			if (dfn[i] == -1)
				tarjan(i, i);
		}

		Arrays.fill(outDegree, 0);
		for (int u = 1; u <= n; u++) {
			for (int i = head[u]; i != -1; i = e[i].next) {
				if (belong[u] != belong[e[i].v])
					outDegree[belong[u]]++;
			}
		}

		int res = 0;
		for (int i = 1; i <= bccId; i++) {
			if (outDegree[i] == 0) {
				if (res == 0)
					res = bccSize[i];
				else
					res = -1;
			}
		}
       
		return res == -1 ? 0 : res ;
	}
}

interface Define{
	final int N = 10008;
	final int M = 50008;
}

class InputReader {
	public BufferedReader reader;
	public StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream), 32768);
		tokenizer = null;
	}

	public String next() {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			try {
				tokenizer = new StringTokenizer(reader.readLine());
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return tokenizer.nextToken();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值