代码随想录算法训练营第五十六天|动态规划part6
108.冗余连接
题目链接:108. 冗余的边
文章讲解:代码随想录
思路:
题意隐含
只有一个冗余边
#include <iostream>
#include <vector>
using namespace std;
int n=1001;
vector<int>father(n,0);void init(){for(int i=0;i<n;i++){father[i]=i;}
}
int find(int x){if(father[x]==x) return x;else return father[x]=find(father[x]);
}void join(int u, int v){u=find(u);v=find(v);if(u==v) return;father[v]=u;
}bool isSame(int u,int v){u=find(u);v=find(v);return u==v;
}int main(){int n;cin>>n;init();for(int i=0;i<n;i++){int s,t;cin>>s>>t;if(isSame(s,t)){ //s跟t是否连同 已经连通的话说明当前边冗余cout<<s<<' '<<t<<endl;return 0;}else{join(s,t); }}
}
109.冗余连接II
题目链接:109. 冗余的边II
文章讲解:代码随想录
根据边的入度来考虑
情况1: 存在入度为2的节点
说明这个节点存在冗余的边(存在两个父节点)
此处需要判断删除哪条边
情况2:不存在入度为2的节点 此时存在环对于存在环
应该找出哪条边使得构成环 可以通过并查集来找
#include <iostream>
#include <vector>
using namespace std;int n=1001;
vector<int>father(n,0);
void init(){for(int i=0;i<n;i++){father[i]=i;}
}
int find(int x){if(father[x]==x)return x;else return father[x]=find(father[x]);
}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;father[v]=u;
}bool isTreeAfterRemoveEdge(vector<vector<int>>edges,int deleteEdge){init();for(int i=0;i<edges.size();i++){if(i==deleteEdge) continue;if(isSame(edges[i][0],edges[i][1])){return false;}else{join(edges[i][0],edges[i][1]);}}return true;
}int getRemoveEdge(vector<vector<int>>edges){init();for(int i=0;i<edges.size();i++){if(isSame(edges[i][0],edges[i][1])){return i;}else{join(edges[i][0],edges[i][1]);}}return -1;
}int main(){int n;cin>>n;vector<vector<int>>edges;vector<int>inDegree(n+1,0);for(int i=0;i<n;i++){int s,t;cin>>s>>t;inDegree[t]++;edges.push_back({s,t});}vector<int>vec; //记录入度为2的边(如果有的话就两条边)for(int i=n-1;i>=0;i--){if(inDegree[edges[i][1]]==2){vec.push_back(i);}}if(vec.size()>0){ //情况1if(isTreeAfterRemoveEdge(edges,vec[0])){cout<<edges[vec[0]][0]<<' '<<edges[vec[0]][1];}else{cout<<edges[vec[1]][0]<<' '<<edges[vec[1]][1];}return 0;}else{ //情况2 有环int ans=getRemoveEdge(edges);if(ans>=0) cout<<edges[ans][0]<<' '<<edges[ans][1];}
}