poj 2890 Matrix Multiplication

題意:對一個對焦線元素爲1、k*k的01矩陣在布爾運算的意義下進行2006次冪運算(k<1000 )。求得到的矩陣裏有幾個1。

解法:由於是布爾意義下的運算,k次矩陣乘相當於長度爲k的路徑個數,由於2006>k,因此可以看做求一個圖的傳遞閉包。可以首先強連通分量縮點,記錄每個強連通分量中的點數,在縮點後的圖G ‘上對每個點進行一次dfs,求出此連通分量能到達多少個點,累加每個強連通得到總共有多少條路徑。

import java.io.*;
import java.util.*;

public class Main {
	int maxn = 1010, maxm = 10010;
	class node {
		int be, ne;
		node(int be, int ne) {
			this.be = be;
			this.ne = ne;
		}
	}
	class Tarjan {
		int E[] = new int[maxn], n, len;
		node buf[] = new node[maxm];
		int dfn[] = new int[maxn], low[] = new int[maxn], cnt;
		int stack[] = new int[maxn], top;
		boolean instack[] = new boolean[maxn];
		int id[] = new int[maxn], num[] = new int[maxn], idx;// 1~idx
		void init(int n) {
			this.n = n;
			Arrays.fill(E, -1);
			len = 0;
		}
		void add(int a, int b) {
			buf[len] = new node(b, E[a]);
			E[a] = len++;
		}
		void dfs(int a) {
			dfn[a] = low[a] = ++cnt;
			instack[a] = true;
			stack[top++] = a;
			int b = -1;
			for (int i = E[a]; i != -1; i = buf[i].ne) {
				b = buf[i].be;
				if (dfn[b] == 0) {
					dfs(b);
					if (low[b] < low[a])
						low[a] = low[b];
				} else if (instack[b] && dfn[b] < low[a])
					low[a] = dfn[b];
			}
			if (low[a] == dfn[a]) {
				idx++;
				do {
					b = stack[--top];
					instack[b] = false;
					id[b] = idx;
					num[idx]++;
				} while (b != a);
			}
		}
		void solve() {
			cnt = idx = top = 0;
			Arrays.fill(dfn, 0);
			Arrays.fill(low, 0);
			Arrays.fill(num, 0);
			Arrays.fill(instack, false);
			for (int i = 1; i <= n; i++)
				if (dfn[i] == 0)
					dfs(i);
			shrink();
			System.out.println(dp.solve());
		}

		void shrink() {
			dp.init(idx);
			for (int a = 1; a <= n; a++)
				for (int i = E[a]; i != -1; i = buf[i].ne) {
					int b = buf[i].be;
					if (id[a] != id[b])
						dp.add(id[a], id[b]);
				}
			for (int i = 1; i <= idx; i++)
				dp.num[i] = num[i];
		}
	}

	class DP {
		int E[] = new int[maxn], n, len;
		node buf[] = new node[maxm];
		int num[] = new int[maxn], vis[] = new int[maxn],
				sum[] = new int[maxn];
		void init(int n) {
			this.n = n;
			Arrays.fill(E, -1);
			len = 0;
		}
		void add(int a, int b) {
			buf[len] = new node(b, E[a]);
			E[a] = len++;
		}
		void dfs(int a, int p) {
			vis[a] = 1;
			for (int i = E[a]; i != -1; i = buf[i].ne) {
				int b = buf[i].be;
				if (vis[b] == 0) {
					dfs(b, p);
					sum[p] += num[b];
				}
			}
		}
		int solve() {
			int res = 0;
			Arrays.fill(sum, 0);
			for (int i = 1; i <= n; i++) {
				Arrays.fill(vis, 0);
				dfs(i, i);
			}
			for(int i=1;i<=n;i++)
				res+=num[i]*(num[i]+sum[i]);
			return res;
		}
	}
	DP dp = new DP();
	Tarjan tj = new Tarjan();
	StreamTokenizer in = new StreamTokenizer(new BufferedReader(
			new InputStreamReader(System.in)));
	int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}
	int n, m;
	void run() throws IOException {
		while (in.nextToken() != in.TT_EOF) {
			n = (int) in.nval;
			m = nextInt();
			tj.init(n);
			while(m-->0)
				tj.add(nextInt()+1, nextInt()+1);
			tj.solve();
		}
	}
	public static void main(String[] args) throws IOException {
		new Main().run();
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章