Codeforces 274D (168D) Lovely Matrix
問題
nxm行列がlovelyであるとは、行列の各行がそれぞれ単調非減少数列になっていることを言う。
今、lovelyだった行列の要素をいくつか-1に変え、
列をいくつか入れ替えた行列が与えられる。
元の行列としてありうるものをどれか一つ求め、
元の行列のi番目の列には、与えられた行列の何番目の列が対応するかをそれぞれ出力せよ。
存在しない場合は-1を出力せよ。
制約条件
nm≦10^5
方針
i列目にそれぞれに対応する頂点を作り、
a[k][i] < a[k][j]のときにiからjの頂点に辺を張ったグラフを考える。
(ただし、a[k][i]またはa[k][j]が-1のときは張らない)
このグラフがトポロジカルソート可能なら、
そのトポロジカル順が解の一つになっている。
ただし、同じ数字が何度か出てくるので、
a[k][i] < a[k][j]なる頂点全てに辺を張ろうとするとO(nm^2)時間がかかってしまい無理。
そこで、a[k][i]が同じであるようなiから、ダミーの頂点xへ辺を張り、
ダミーの頂点xから、a[k][i] < a[k][j]であるようなjの頂点へ辺を張るようにする。
(ただし、a[k][j]は、a[k][i]より大きいもののうち最小であるもののみでよい)
すると、張る辺の本数は高々O(nm)本になり、
制限時間内にトポロジカルソートが出来るようになる。
ソースコード
int n, m; vector<vi> e; int main(){ cin >> n >> m; e.resize((n + 3) * (m + 3)); int k = m; rep(i, n){ vector<pi> p; rep(j, m){ int t; cin >> t; p.pb(mp(t, j)); } sort(all(p)); rep(j, m){ if(p[j].first < 0) continue; int nxt = lower_bound(all(p), mp(p[j].first + 1, -1)) - p.begin(); while(j < nxt){ e[k].pb(p[j].second); e[p[j].second].pb(k + 1); j++; } k++; j--; } k++; } vi ord; if(!topologicalSort(e, ord)){ cout << -1 << endl; return 0; } rep(i, ord.size()) if(ord[i] < m) cout << ord[i] + 1 << " "; cout << endl; return 0; }