C123【模板】扩展域并查集 P1892 [BOI2003] 团伙
C123【模板】扩展域并查集 P1892 [BOI2003] 团伙_哔哩哔哩_bilibili
题目:所有人之间有两种关系:朋友和敌人。给 n 个人,m个关系,求最多的团体数。
种类并查集:维护点的连通性和传递性。
扩展成两个域:朋友域(1~n)和敌人域(n+1~2n)。
若是朋友,合并a与b。
若是敌人,合并a与b的敌人,合并b与a的敌人。
统计根的个数即答案。
// 扩展域并查集 #include<bits/stdc++.h> using namespace std; int n,m,ans; int fa[2005]; int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } void unite(int x,int y){ fa[find(y)]=find(x); } int main(){ cin>>n>>m; for(int i=1;i<=2*n;i++) fa[i]=i; for(int i=1,a,b;i<=m;i++){ char ch; cin>>ch>>a>>b; if(ch=='F') unite(a,b); //若是朋友,合并a与b else{ //若是敌人,合并a与b的敌人,合并b与a的敌人 unite(a,b+n); unite(b,a+n); } } for(int i=1;i<=n;i++)if(i==fa[i])ans++; cout<<ans; }
P1525 [NOIP 2010 提高组] 关押罪犯 - 洛谷
// 扩展域并查集 #include<bits/stdc++.h> using namespace std; struct E{ int a,b,c; bool operator<(const E &t)const{ return c>t.c; } }e[100005]; int n,m,fa[40005]; int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } void unite(int x,int y){ fa[find(y)]=find(x); } int main(){ cin>>n>>m; for(int i=1;i<=m;i++)cin>>e[i].a>>e[i].b>>e[i].c; sort(e+1,e+m+1); //按影响力降序 for(int i=1;i<=n*2;i++) fa[i]=i; for(int i=1; i<=m; i++){ //贪心处理影响力大的 int a=e[i].a,b=e[i].b; if(find(a)==find(b)){ //共集则发生冲突 cout<<e[i].c; return 0; } unite(a,b+n); unite(b,a+n); //a,b分投集合 } cout<<0; }
浙公网安备 33010602011771号