Description
贝爷的人生乐趣之一就是约战马会长. 他知道马会长喜欢和怪兽对决,于是他训练了N只怪兽,并对怪兽用0到N-1的整数进行编号. 贝爷训练怪兽的方式是让它们一对一互殴. 两只怪兽互殴会发生以下三种可能的结果:
1) 什么事也没发生
2) 第一只怪兽永远消失
3) 第二只怪兽永远消失
怪兽们经过了旷日持久的互殴. 贝爷不知道哪些怪兽进行了互殴也不知道它们互殴的顺序,但他确信无论经过多少次互殴,总有一些怪兽能存活下来,他将要派这些怪兽去和马会长对决. 现在他想知道至少有多少只怪兽能存活下来,你能帮他算出来吗?
请实现下面Solution类中的minLeftMonsters函数,完成上述功能.
参数G: N*N(1 <= N <= 50)字符矩阵,G[i][j]表示怪兽i和怪兽j互殴会发生的结果. 字符‘+’代表怪兽i会消失,’-’代表怪兽j会消失,数字’0’则代表什么都没发生. 输入保证G[i][i]一定是’0’,而且G[i][j]和G[j][i]一定相反(’-’和’+’互为相反,’0’和自身相反).
返回值:怪兽存活的最少数目.
class Solution {
public:
int minLeftMonsters(vector< vector<char> > G) {}
}
class Solution {
private:
vector<int> pre, lowlink, sccno;
stack<int> S;
vector< vector<int> > V;
vector<bool> vis;
int dfs_clock, scc_cnt;
void dfs(int u)
{
pre[u] = lowlink[u] = ++ dfs_clock;
S.push(u);
for (int i=0; i<V[u].size(); i++)
{
int v = V[u][i];
if (!pre[v])
{
dfs(v);
lowlink[u] = min(lowlink[u], lowlink[v]);
}
else if (!sccno[v]) lowlink[u] = min(lowlink[u], pre[v]);
}
if (lowlink[u] == pre[u])
{
scc_cnt ++;
for (;;)
{
int x = S.top();
S.pop();
sccno[x] = scc_cnt;
if (x == u) break;
}
}
}
void find_scc(int n)
{
dfs_clock = scc_cnt = 0;
for (int i=0; i<n; i++) sccno[i] = pre[i] = 0;
for (int i=0; i<n; i++) if (!pre[i]) dfs(i);
}
public:
int minLeftMonsters(vector< vector<char> > G) {
int res, n, x, i, j;
n = G.size();
V.resize(n);
pre.resize(n);
lowlink.resize(n);
sccno.resize(n);
vis.resize(n + 1);
for (i=0; i<n; i++)
for (j=0; j<n; j++)
if (G[i][j] == '-') V[i].push_back(j);
find_scc(n);
for (i=1; i<=scc_cnt; i++) vis[i] = false;
res = scc_cnt;
for (i=0; i<n; i++)
for (j=0; j<V[i].size(); j++)
{
x = sccno[V[i][j]];
if (x == sccno[i]) continue;
if (!vis[x])
{
res --;
vis[x] = true;
}
}
for (i=0; i<n; i++) V[i].clear();
V.clear();
pre.clear();
lowlink.clear();
sccno.clear();
vis.clear();
while (!S.empty()) S.pop();
return res;
}
};