CodeForces - 402E Strictly Positive Matrix(tarjan求连通分量个数)

CF402E Strictly Positive Matrix

题目大意:

给出一个矩阵a,满足\(a_{ij} \geq 0\)\(\sum_{i=1}^n a_{ii} > 0\),问是否存在k使得\(a^k\)为一个严格正矩阵。

若b为严格正矩阵则满足任意的\(b_{ij} > 0\)

思路:

题目满足a中元素都是非负的,结合矩阵乘法的性质可以发现,我们并不关心a矩阵中具体的数值,只关心它是否为0,考虑将a矩阵转换为一个01矩阵。由01矩阵联想到邻接矩阵,对于某一个邻接矩阵D,如果 \(d_{i,j}=1\) 则表示i,j间有一条边,那么严格正矩阵的含义就是任意的两点都存在一条边,就可以使用tarjan来求连通分量个数进行判断。

Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
const int INF = 0x3f3f3f3f;

struct Node {
	int to, next;
} e[N * N * 2];
int head[N], tot;
int dfn[N], low[N], num;
int col;
bool isIns[N];
int st[N], top;

int n;
bool mp[N][N], hasZero;

void add_edge(int u, int v) {
	e[++tot].to = v;
	e[tot].next = head[u];
	head[u] = tot;
}

void tarjan(int u) {
	dfn[u] = low[u] = ++num;
	isIns[u] = 1;
	st[++top] = u;
	for (int i = head[u]; ~i; i = e[i].next) {
		int v = e[i].to;
		if (!dfn[v]) {
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if (isIns[v]) {
			low[u] = min(low[u], dfn[v]);
		}
	}
	if (low[u] == dfn[u]) {
		++col;
		while (st[top] != u) {
			isIns[st[top--]] = 0;
		}
		isIns[st[top--]] = 0;
	}
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	memset(head, -1, sizeof(head));
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			int t; cin >> t;
			if (t)
				mp[i][j] = 1;
			else
				hasZero = 1;
		}
	}
	if (!hasZero) {
		cout << "YES" << endl;
		return 0;
	}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (mp[i][j])
				add_edge(i, j);
	for (int i = 1; i <= n; i++)
		if (!dfn[i])
			tarjan(i);
	if (col == 1)
		cout << "YES" << endl;
	else
		cout << "NO" << endl;
	return 0;
}
posted @ 2021-01-20 19:15  Nepenthe8  阅读(63)  评论(0编辑  收藏  举报