https://community.topcoder.com/stat?c=problem_statement&pm=7512
島が’.‘,海が’.‘で表された盤面が与えられる.島は上下左右斜めで隣接しているとき,同じグループの島となる.島が島を内包しているとき,内包している島のレベルの$max + 1$がその島のレベルとなる.内包している島を持っていない場合,その島のレベルは$0$である.各レベルの島の数を返す.
まずレベルは考えずに島の内包関係をグラフで表現する.盤面外に出ること無しで,海を伝って他の島に当たった数を保持しておき,その数が最大のものに内包されているとした.内包関係をグラフで表現した後は,トポロジカルソートをしてトポロジカル順序で島のレベルを確定させていった.
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define REP(i,k,n) for(int i=k;i<(int)(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define INF 1<<30
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
int h, w;
int id[55][55];
int dx[4] = { 1, 0,-1, 0};
int dy[4] = { 0, 1, 0,-1};
int dx2[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
int dy2[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
bool inside(int y, int x) {
if(0 <= y && y < h && 0 <= x && x < w) return true;
return false;
}
int counter = 0;
bool visited[55][55];
vector<string> s;
void dfs(int y, int x) {
rep(i, 8) {
int ny = y + dy2[i];
int nx = x + dx2[i];
if(inside(ny, nx) && !visited[ny][nx] && s[ny][nx] == 'x') {
id[ny][nx] = counter;
visited[ny][nx] = true;
dfs(ny, nx);
}
}
}
int myid = -1;
bool outflag = false;
map<int, int> m;
void dfs2(int y, int x) {
if(outflag) return;
rep(i, 4) {
int ny = y + dy[i];
int nx = x + dx[i];
if(visited[ny][nx]) continue;
if(!inside(ny, nx)) {
outflag = true;
return;
}
if(s[ny][nx] == '.') {
visited[ny][nx] = true;
dfs2(ny, nx);
} else {
int t = id[ny][nx];
if(t != myid) {
visited[ny][nx] = true;
m[id[ny][nx]]++;
} else {
visited[ny][nx] = true;
dfs2(ny, nx);
}
}
}
}
vector<int> G[55 * 55], out;
bool used[55 * 55];
void tposo(int cur) { // topologicalsort-dfs
used[cur] = true;
rep(i,G[cur].size()) {
int v = G[cur][i];
if(!used[v]) tposo(v);
}
out.push_back(cur);
}
class LandAndSea {
public:
vector <int> howManyIslands(vector <string> seaMap) {
s = seaMap;
h = seaMap.size();
w = seaMap[0].size();
counter = 0;
memset(id, -1, sizeof(id));
memset(visited, false, sizeof(visited));
rep(i, 55) G[i].clear();
out.clear();
vector<P> start;
rep(i, h) {
rep(j, w) {
if(visited[i][j]) continue;
if(s[i][j] == '.') continue;
id[i][j] = counter;
visited[i][j] = true;
start.push_back(mp(i, j));
dfs(i, j);
counter++;
}
}
int indeg[55 * 55];
memset(indeg, 0, sizeof(indeg));
rep(i, counter) {
m.clear();
myid = i;
outflag = false;
memset(visited, false, sizeof(visited));
visited[start[i].fi][start[i].se] = true;
dfs2(start[i].fi, start[i].se);
if(outflag) continue;
int parent = -1, vmax = 0;
each(it, m) {
if(it->second > vmax) {
parent = it->first;
vmax = it->second;
}
}
G[i].push_back(parent);
indeg[parent]++;
}
memset(used, 0, sizeof(used));
rep(i, counter) {
if(!used[i]) tposo(i);
}
reverse(out.begin(), out.end());
map<int, int> ans;
vector<int> dp(counter);
rep(i, out.size()) {
int id = out[i];
ans[dp[id]]++;
rep(j, G[id].size()) {
dp[G[id][j]] = max(dp[G[id][j]], dp[id] + 1);
}
}
vector<int> res(ans.size());
rep(i, ans.size()) res[i] = ans[i];
return res;
}
};