海珠区专业做网站公司网络营销推广工具有哪些
K LilaS的特殊图判断 - 第七届校赛正式赛 —— 补题
题目大意:
给定一个无向图,图中有 N N N 个顶点,编号为 1 − N 1-N 1−N , M M M 条边,编号为 1 − M 1-M 1−M 。第 i i i 条边连接顶点 u i u_i ui 和 v i v_i vi 。存在重边和自环。
有没有一种算法能快速判断该无向图中的每个连通部分是否满足:连通部分的顶点和边的数量相同
如果该图中每个连通部分都满足条件,则输出
Yes
;否则,输出No
。1 < = N < = 2 ∗ 1 0 5 1<=N<=2*10^5 1<=N<=2∗105
0 < = M < = 2 ∗ 1 0 5 0<=M<=2*10^5 0<=M<=2∗105
1 < = u i < = v i < = N 1<=u_i<=v_i<=N 1<=ui<=vi<=N
思路:
考虑并查集,维护祖先节点中 顶点个数 和 边的个数
int fa[N],sz[N],ver[N];fa[i]=i,sz[i]=1,ver[i]=0;int u,v;
u=find(u),v=find(v);
如果祖先节点相同,那么点的个数不用增加,考虑给祖先节点多加一条边if(u==v){ver[u]++;}
如果祖先节点不相同,那么将这两个连通块合并,随便找一个节点为祖宗节点即可else{fa[v]=u;sz[u]+=sz[v];ver[u]+=ver[v]+1;//这条边}
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define fi first
#define se second
#define PII pair<int,int>
#define lowbit(x) x&-x
#define ALL(x) x.begin(),x.end()const int mod = 1e9 + 7;
const int N = 2e5 + 10;int fa[N],sz[N],ver[N];
int n,m;
int find(int x){if(x==fa[x]) return x;return fa[x]=find(fa[x]);
}void solve() {cin>>n>>m;for(int i=1;i<=n;i++){fa[i]=i;sz[i]=1;ver[i]=0;}for(int i=1;i<=m;i++){int u,v;cin>>u>>v;u=find(u),v=find(v);if(u==v){ver[u]++;continue;}if(u!=v){fa[v]=u;sz[u]+=sz[v];ver[u]+=ver[v]+1;}else{ver[u]++;}}// cout<<'\n';for(int i=1;i<=n;i++){int u=find(i);
// cout<<sz[u]<<" "<<ver[u]<<'\n';if(sz[u]!=ver[u]){cout<<"No\n";return ;}}cout<<"Yes\n";
}signed main() {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int T = 1;
// cin >> T;while (T--) {solve();}return 0;
}