1.
模板题:多余的边
思路:n条边n个点。类似于克鲁斯卡尔,加边的同时用并查集判断边的两端点是否同根,若同根,则要删除该边。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2000;
int main()
{int n;cin>>n;vector<int>fa(n+1);for(int i=1;i<=n;i++)fa[i]=i;auto find=[&](auto &&find,int x)->int{if(fa[x]==x)return x;return fa[x]=find(find,fa[x]);};auto join=[&](int x,int y)->int{int xx=find(find,x);int yy=find(find,y);if(xx==yy)return 1;fa[xx]=yy;return 0;};int a,b;for(int i=0;i<n;i++){int s,t;cin>>s>>t;if(join(s,t)){a=s;b=t;}}cout<<a<<' '<<b<<'\n';
}
2.
多余的边(二)
思路:n条边n个点。与模板题不同的是该图是有向图。
分为三种情况(见力扣评论区):
(1)每个点入度是1,有一个有向环。解决:同模板题,随便删除环上一边。
(2)存在一个入度为2的点,无有向环。解决:随便删除指向该点的两条边中的其中一条。
(3)既存在有向环,又存在一个入度为2的点(肯定在环上)。解决:肯定要删除环上指向入度为2点的那条边,用并查集。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2000;
vector<int>v[N];
int main()
{int n;cin>>n;vector<int>fa(n+1);vector<int>in(n+1);for(int i=1;i<=n;i++)fa[i]=i;auto find=[&](auto &&find,int x)->int{if(fa[x]==x)return x;return fa[x]=find(find,fa[x]);};auto join=[&](int x,int y)->int{int xx=find(find,x);int yy=find(find,y);if(xx==yy)return 1;fa[xx]=yy;return 0;};int a,b;int f=0;for(int i=0;i<n;i++){int s,t;cin>>s>>t;if(f)continue;//搞定入度为2的点就成功了v[t].push_back(s);//反着存,方便找指向入度为2点的边in[t]++;if(in[t]>1){f=1;if(join(s,t))a=s,b=t;else a=v[t][0],b=t;continue;}if(join(s,t)){a=s;b=t;}}cout<<a<<' '<<b<<'\n';
}
