反向圖+拓撲排序 or 染色:Leetcode802 找到最終的安全狀態
問題:
思路:
反向圖+拓撲排序:
對於一個節點 u,如果我們從 u 開始任意行走能夠走到一個環裏,那麼 u 就不是一個安全的節點。換句話說,u 是一個安全的節點,當且僅當 u 直接相連的節點(u 的出邊相連的那些節點)都是安全的節點。
對於沒有出度的節點,一定是最終安全的節點,而僅直接指向它的節點(出度爲1,且指向沒有出度的節點)也是最終安全的節點。以此類推,這樣我們可以將所有的邊全部反向,首先所有沒有任何入度的節點都是安全的,我們把這些節點全部移除。隨後新的圖中沒有任何入度的節點都是安全的。
我們發現這種做法實際上就是對圖進行拓撲排序,將原問題轉化爲了拓撲排序問題
染色:
對於每個節點,有三種染色方法:白色表示節點尚未被訪問(用0表示),灰色表示該節點在此輪搜索中已被訪問過或該節點在環中(用1表示),黑色表示該節點的所有相連節點已被訪問,且該節點不在環中(用2表示)
對每個節點進行DFS,DFS函數的功能爲判斷該節點是否爲黑色節點或能被染成黑色。
進入DFS後,判斷該節點是否已經被染過色,若已染成黑色,直接返回TRUE,染成灰色直接返回FALSE
若未被染色,先將其染成灰色
只有與該節點相連的所有節點都爲黑色節點或能被染成黑色,該節點才能被染成黑色,並返回TRUE(u 是一個安全的節點,當且僅當 u 直接相連的節點都是安全的節點),否則返回FALSE
代碼:
反向圖+拓撲排序:
class Solution {
public:
vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
int* indegree;
vector<int> ans;
indegree=(int*)malloc( graph.size()*sizeof(int) );
int i;
for( i=0;i<graph.size();i++ )
{
indegree[i]=0;
}
int j;
for( i=0;i<graph.size();i++ )
indegree[i]=graph[i].size();
vector<vector<int>> reverse_graph;
for( i=0;i<graph.size();i++ )
reverse_graph.push_back( vector<int>() );
for( i=0;i<graph.size();i++ )
{
for( j=0;j<graph[i].size();j++ )
reverse_graph[ graph[i][j] ].push_back(i);
}
stack<int> st;
for( i=0;i<graph.size();i++ )
{
if( indegree[i]==0 )
st.push( i );
}
int temp;
while( st.size()!=0 )
{
temp=st.top();
ans.push_back(temp);
st.pop();
for( i=0;i<reverse_graph[temp].size();i++ )
{
indegree[ reverse_graph[temp][i] ]--;
if( indegree[ reverse_graph[temp][i] ]==0 )
st.push( reverse_graph[temp][i] );
}
}
sort( ans.begin(),ans.end() );
return ans;
}
};
染色:
class Solution {
public:
bool dfs( int i,vector<vector<int>>& graph,int* color )
{
if( color[i]>0 )
return color[i]==2;
color[i]=1;
int j;
for( j=0;j<graph[i].size();j++ )
{
if( color[ graph[i][j] ]==2 )
continue;
else if( color[ graph[i][j] ]==1 || !dfs( graph[i][j],graph,color ) )
return false;
}
color[i]=2;
return true;
}
vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
int* color;
color=(int*)malloc( graph.size()*sizeof(int) );
int i;
for( i=0;i<graph.size();i++ )
color[i]=0;
vector<int> ans;
for( i=0;i<graph.size();i++ )
{
if( dfs( i,graph,color ) )
ans.push_back(i);
}
return ans;
}
};