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;
}