题目描述有点长,就不放这了,简单来说就是如何找到无向无环图中的冗余边。
非常标准的模板题啊,因为我们要知道并查集中的isSame函数就是专门用来查图中节点的链接情况的,如果一个点出现了冗余边,产生冗余边的两个节点就是符合isSame的要求,所以我们只需要在构建图的过程中不断判断两个点是否isSame即可。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
int n;
vector<int> father(1001);
void init(){
for(int i=1;i<=n;++i){
father[i]=i;
}
}
int find(int u){
return father[u]==u?u:father[u]=find(father[u]);
}
bool isSame(int u,int v){
u=find(u);
v=find(v);
return u==v;
}
void join(int u,int v){
u=find(u);
v=find(v);
if(u==v)return;
else father[v]=u;
}
int main(){
cin>>n;
int s,t;
init();
for(int i=0;i<n;++i){
cin>>s>>t;
if(isSame(s,t)){
cout<<s<<" "<<t<<endl;
return 0;
}
else{
join(s,t);
}
}
return -1;
}
这个题相比起上一个题,只是将无向图换成了有向图,但是我们要判断的东西就多了不少。
比起无向图来说,我们的冗余边的情况要复杂一些,我们可以通过每个点的入度来作为判断的标准:更具体地说,我们产生冗余边有两种情况,一种是有向环图,一种是有向的无环图。环图的话 不会出现入度为2的点,那么我们直接去删除环中的一条边即可;反之如果我们找到入度为2的点,那么我们还要考虑删除哪条边能保证删除后的图仍然是有向图。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
int n;
vector<int> father(1001);
void init(){
for(int i=0;i<n;++i){
father[i]=i;
}
}
int find(int u){
return u==father[u]?u:father[u]=find(father[u]);
}
bool same(int u,int v){
u=find(u);
v=find(v);
return u==v;
}
void join(int u,int v){
u=find(u);
v=find(v);
if(u==v)return;
father[v]=u;
}
bool isTreeAfterRemove(const vector<vector<int>>& edges,int deleteEdge){
init();
for(int i=0;i<n;++i){
if(i==deleteEdge)continue;
if(same(edges[i][0],edges[i][1]))return false;
join(edges[i][0],edges[i][1]);
}
return true;
}
void getRemove(const vector<vector<int>>& edges){
init();
for(int i=0;i<n;++i){
if(same(edges[i][0],edges[i][1])){
cout<<edges[i][0]<<" "<<edges[i][1]<<endl;
return;
}
join(edges[i][0],edges[i][1]);
}
}
int main(){
cin>>n;
int s,t;
vector<vector<int>> edges;
vector<int> inDegrees(n+1,0);
for(int i=0;i<n;++i){
cin>>s>>t;
edges.push_back({s,t});
inDegrees[t]++;
}
vector<int> vec;
for(int i=n-1;i>=0;--i){
if(inDegrees[edges[i][1]]==2)vec.push_back(i);
}
if(vec.size()>0){
if(isTreeAfterRemove(edges,vec[0]))cout<<edges[vec[0]][0]<<" "<<edges[vec[0]][1]<<endl;
else cout<<edges[vec[1]][0]<<" "<<edges[vec[1]][1]<<endl;
return 0;
}
getRemove(edges);
}