题意
题解
考虑同行同列的数字较小值向较大值连边,得到一个 D A G DAG DAG,则问题转化为求解拓扑序。对于同行或列相同值元素,它们秩相同,若相互连边,图中会出现环,那么将其看做一个点;用并查集维护一个同行或列相同值元素构成的连通分量,用根节点代表原图各点进行连边。
class Solution
{
#define maxn 500
typedef pair<int, int> P;
public:
int n, m, deg[maxn * maxn], rec[maxn * maxn], par[maxn * maxn], rnk[maxn * maxn];
P r[maxn][maxn], c[maxn][maxn];
vector<int> G[maxn * maxn];
void init(int n)
{
for (int i = 0; i < n; ++i)
par[i] = i, rnk[i] = 0;
}
int find(int x)
{
return par[x] == x ? x : (par[x] = find(par[x]));
}
void unite(int x, int y)
{
x = find(x), y = find(y);
if (x == y)
return;
if (rnk[x] > rnk[y])
par[y] = x;
else
{
par[x] = y;
if (rnk[x] == rnk[y])
++rnk[y];
}
}
vector<vector<int>> matrixRankTransform(vector<vector<int>> &matrix)
{
n = matrix.size(), m = matrix[0].size();
int sz = n * m;
init(sz);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
r[i][j] = P(matrix[i][j], i * m + j);
sort(r[i], r[i] + m);
for (int j = 1; j < m; ++j)
{
if (r[i][j - 1].first == r[i][j].first)
unite(r[i][j - 1].second, r[i][j].second);
}
}
for (int j = 0; j < m; ++j)
{
for (int i = 0; i < n; ++i)
c[j][i] = P(matrix[i][j], i * m + j);
sort(c[j], c[j] + n);
for (int i = 1; i < n; ++i)
{
if (c[j][i - 1].first == c[j][i].first)
unite(c[j][i - 1].second, c[j][i].second);
}
}
for (int i = 0; i < n; ++i)
for (int j = 1; j < m; ++j)
if (r[i][j - 1].first != r[i][j].first)
{
int u = find(r[i][j - 1].second), v = find(r[i][j].second);
++deg[v];
G[u].push_back(v);
}
for (int j = 0; j < m; ++j)
for (int i = 1; i < n; ++i)
if (c[j][i - 1].first != c[j][i].first)
{
int u = find(c[j][i - 1].second), v = find(c[j][i].second);
++deg[v];
G[u].push_back(v);
}
queue<int> q;
for (int i = 0; i < sz; ++i)
{
if (!deg[i] && par[i] == i)
q.push(i);
}
while (!q.empty())
{
int v = q.front();
q.pop();
for (int i = 0; i < G[v].size(); ++i)
{
int u = G[v][i];
rec[u] = max(rec[u], rec[v] + 1);
if (--deg[u] == 0)
q.push(u);
}
}
vector<vector<int>> res(n, vector<int>(m));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
res[i][j] = rec[find(i * m + j)] + 1;
return res;
}
};