题目描述:
在本问题中,有根树指满足以下条件的有向图。该树只有一个根节点,所有其他节点都是该根节点的后继。每一个节点只有一个父节点,除了根节点没有父节点。
输入一个有向图,该图由一个有着N个节点 (节点值不重复1, 2, ..., N) 的树及一条附加的边构成。附加的边的两个顶点包含在1到N中间,这条附加的边不属于树中已存在的边。
结果图是一个以边
组成的二维数组。 每一个边
的元素是一对 [u, v]
,用以表示有向图中连接顶点 u
and v
和顶点的边,其中父节点u
是子节点v
的一个父节点。
返回一条能删除的边,使得剩下的图是有N个节点的有根树。若有多个答案,返回最后出现在给定二维数组的答案。
示例 1:
输入: [[1,2], [1,3], [2,3]] 输出: [2,3] 解释: 给定的有向图如下: 1 / \ v v 2-->3
示例 2:
输入: [[1,2], [2,3], [3,4], [4,1], [1,5]] 输出: [4,1] 解释: 给定的有向图如下: 5 <- 1 -> 2 ^ | | v 4 <- 3
注意:
- 二维数组大小的在3到1000范围内。
- 二维数组中的每个整数在1到N之间,其中 N 是二维数组的大小
思路:
首先利用DFS判断是否有环,如果有环的话,就把成环的最后一条边删了,如果无环的话,就找到入度为2的点,然后从后往前遍历,把最后一个入度为该点的边给删去
class Solution {
public:
bool DFS(vector<int> &visited, vector<vector<int> > &node, int start, int next_node, vector<int> &loopedge){
if(visited[next_node]==1){
loopedge[0]=start;
loopedge[1]=next_node;
return true;
}
visited[next_node]=1;
for(int i=0; i<node[next_node].size(); ++i){
return DFS(visited, node, next_node, node[next_node][i], loopedge);
}
visited[next_node]=0;//记得归还状态
return false;
}
vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
int len=edges.size();
if(len<=1 || edges[0].size()==0){
vector<int> ret;
return ret;
}
vector<vector<int> > node;
for(int i=0; i<=len; ++i){
vector<int> re;
node.push_back(re);
}
vector<int> visited(len+1, 0);
vector<int> indegrees(len+1, 0);
for(int i=0; i<len; ++i){
node[edges[i][0]].push_back(edges[i][1]);
indegrees[edges[i][1]]++;//入度+1
}
int startNode=0;
for(int i=1; i<=len; ++i){
if(indegrees[i]==0)//说明需要在这个点删除一条边
startNode=i;
}
if(startNode==0)
startNode=1;
//判断是否有环
vector<int> loopEdge={-1,-1};
bool isLoop = DFS(visited, node, -1, startNode, loopEdge);
if(!isLoop){
//说明没有环,没有环就直接找度为2的点,然后删了最后一条入度为该点的边
int endNode;
for(int i=1; i<=len; ++i){
if(indegrees[i]==2)//说明需要在这个点删除一条边
endNode = i;
}
for(int i=len-1; i>=0; --i){
if(edges[i][1]==endNode)
return edges[i];
}
}
else
return loopEdge;
}
};