Solution
输入的边有N条,其中有一条为“附加边”,但我们不知道是哪条边。
但这条边的存在会使得原本的有根树出现严格一个环(不考虑方向)。
我们一边加边,一边将两端点用并查集合并,
当两端点在合并前就属于同一个并查集时,说明加上这条边后就会出现环
于是就找到了原图中唯一的环,我们用dfs将环上的点标记
最后倒序枚举输入的边,若当前边在环上,且删去后图中入度为0的点有且只有一个,那么就找到了答案
Code
class Solution {
public:
int N, fa[1000 + 7], in[1000 + 7];
int find(int x) {return x == fa[x] ? x:fa[x] = find(fa[x]);}
vector<int>to[1000 + 7];
int st, ed;
bool vis[1000 + 7];
bool dfs(int u,int f) {
vis[u] = true;
if(u == ed) return true;
for(int i = 0;i < to[u].size();++i) {
int v = to[u][i]; if(v == f) continue;
if(dfs(v,u)) return true;
vis[v] = false;
} return false;
}
vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
N = edges.size();
vector<int>root;
for(int i = 1;i <= N;++i) fa[i] = i;
for(int i = 0;i < N;++i) {
int u = edges[i][0], v = edges[i][1];
in[v]++;
int f1 = find(u), f2 = find(v);
if(f1 == f2) {
st = u, ed = v;
} else {
fa[f1] = f2;
to[u].push_back(v); to[v].push_back(u);
}
}
for(int i = 1;i <= N;++i) if(in[i] == 0) root.push_back(i);
//debug2(st,ed);
dfs(st,st);
vector<int>res;
for(int i = N - 1;i>=0;--i) {
int u = edges[i][0], v = edges[i][1];
if(!vis[u] || !vis[v]) continue;
--in[v];
if(root.size() == 1 && in[v] == 0) continue;
if(root.size() == 0 && in[v] != 0) continue;
res.push_back(u), res.push_back(v);break;
}
return res;
}
};