题单:并查集模板题 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
P2256 一中校运会之百米跑
用一个map存储名字和他的序号,然后就是普通的并查集了
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define all(a) begin(a), end(a)
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e6+10;
int k,t,n,ans,p[N];
unordered_map<string,int> m;
string s,s1,s2;
int find(int x)
{
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>t;
for(int i=1;i<=n;i++)
{
cin>>s;
m[s]=i;p[m[s]]=i;
}
for(int i=1;i<=t;i++)
{
cin>>s1>>s2;
int a=m[s1],b=m[s2];
p[find(a)]=find(b);
}
cin>>k;
while(k--)
{
cin>>s1>>s2;
int a=m[s1],b=m[s2];
if(find(a)==find(b))cout<<"Yes."<<endl;
else cout<<"No."<<endl;
}
return 0;
}
P2814 家谱
用map存储string和string
#include<bits/stdc++.h>
using namespace std;
map<string,string>p;
string find(string x)
{
if(x!=p[x])
p[x]=find(p[x]);
return p[x];
}
string s,s1;
int main()
{
char ch;
cin>>ch;
while(ch!='$')
{
cin>>s;
if(ch=='#')
{
s1=s;
if(p[s]=="") p[s]=s;
}
else if(ch=='+')
p[s]=s1;
else
cout<<s<<' '<<find(s)<<endl;
cin>>ch;
}
return 0;
}
P2078 朋友
难点在于有一组是负数,我们还是可以用一个map<int,int>来解决这个问题,结果就是和1,-1相连个数中较小的那一个。
#include <bits/stdc++.h>
using namespace std;
int n, m, p, q, u, v, tat, tot;
map<int, int> f;
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
void judge(int x, int y)
{
f[find(x)] = find(y);
}
int main()
{
cin>>n>>m>>p>>q;
for (int i = -m; i <= n; i++)
f[i] = i;
for (int i = 1; i <= p + q; i++)
{
cin>>u>>v;
judge(u, v);
}
for (int i = -m; i <= -1; i++)
{
if (find(f[i])==find(-1) )
tat++;
}
for (int i = 1; i <= n; i++)
{
if (find(f[i])==find(1) )
tot++;
}
cout<<min(tat, tot);
return 0;
}
P1111 修复公路
排序+并查集,如何计算有多少个挂为同一组了呢,判断if(fx!=fy)f[fx]=fy,n--;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct hh
{
int x,y,t;
}a[200000];
int f[200000],n,m;
int cmp(const hh &a,const hh &b){return a.t<b.t;}
int find(int x){return f[x]==x?x:(f[x]=find(f[x]));}
int main()
{
cin>>n>>m;
if(n==1){cout<<0;return 0;}
for(int i=1;i<=m;i++)cin>>a[i].x>>a[i].y>>a[i]. t;
sort(a+1,a+m+1,cmp);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++)
{
int fx=find(a[i].x),fy=find(a[i].y);
if(fx!=fy)f[fx]=fy,n--;
if(n==1){cout<<a[i].t;return 0;}
}
cout<<-1<<endl;
return 0;
}
P1455 搭配购买
01背包+并查集
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define all(a) begin(a), end(a)
#define pb(x) push_back(x)
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e5+10;
int t,n,m,mo,ans;
int w[N],v[N],p[N],f[N];
bool st[N];
int find(int x)
{
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m>>mo;
for(int i=1;i<=n;i++)
{
p[i]=i;
}
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
}
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
p[find(a)]=find(b);
}
for(int i=1;i<=n;i++)
{
if(p[i]!=i)
{
int cc=find(i);
w[cc]+=w[i];
w[i]=0;
v[cc]+=v[i];
v[i]=0;
}
}
for(int i=1;i<=n;i++)
{
for(int j=mo;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
cout<<f[mo];
return 0;
}
P3958 [NOIP2017 提高组] 奶酪
很好的题目,我们对于每次输入要进行一个预处理,即是否和上边界下边界相连,然后在依次两两对比,在范围内就相连。
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
int n,h,r,fa[1010],T;
int x[1010],y[1010],z[1010];
double dis(double xa,double ya,double za,double xb,double yb,double zb)//套公式
{
return (double)(sqrt((double)(xa-xb)*(xa-xb)+(double)(ya-yb)*(ya-yb)+(double)(za-zb)*(za-zb)));
}
int find(int s)
{
if(fa[s]!=s)fa[s]=find(fa[s]);
return fa[s];
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&h,&r);
for(int a=0;a<=n+1;a++)
{
fa[a]=a;
}
for(int a=1;a<=n;a++)
{
scanf("%d%d%d",&x[a],&y[a],&z[a]);
if(z[a]-r<=0)
{
if(find(a)!=find(0))
{
fa[find(a)]=find(0);
}
}
if(z[a]+r>=h)
{
if(find(a)!=find(n+1))
{
fa[find(a)]=find(n+1);
}
}
for(int b=1;b<a;b++)
{
if(2*r>=dis(x[a],y[a],z[a],x[b],y[b],z[b]))
{
if(find(a)!=find(b))
{
fa[find(a)]=find(b);
}
}
}
}
if(find(0)==find(n+1))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}
837. 连通块中点的数量
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define YES puts("YES");
#define NO puts("NO");
#define all(a) begin(a), end(a)
#define x first
#define y second
#define pb(x) push_back(x)
typedef long long ll;
const int N=1e5+10;
ll t,n,m,k,q,l,r;
int p[N],cnt[N];
int find(int x)
{
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
p[i]=i;cnt[i]=1;
}
while(m--)
{
string s;int a,b;
cin>>s;
if(s=="C")
{
cin>>a>>b;
int x=find(a), y=find(b);
if(x!=y)
{
p[x]=y;
cnt[y]+=cnt[x];
}
}
else if(s=="Q1")
{
cin>>a>>b;
if(find(a)==find(b))
cout<<"Yes"<<"\n";
else
cout<<"No"<<"\n";
}
else
{
cin>>a;
cout<<cnt[find(a)]<<endl;
}
}
return 0;
}