3/25《并查集》
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3/25《并查集》相关的知识,希望对你有一定的参考价值。
P1892 [BOI2003]团伙
数组记录敌人;且在每次合并前,先合并别人的敌人
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e4+5;
int p[maxn],f[maxn],n,m;
int r_find(int r)
if(f[r]==r)
return r;
f[r]=r_find(f[r]);
return f[r];
int main()
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++)
char c;int a,b;
cin>>c>>a>>b;
if(c=='F')
int fx=r_find(a),fy=r_find(b);
f[fx]=fy;
if(c=='E')
if(p[a])
int fx=r_find(p[a]),fy=r_find(b);
f[fx]=fy;
if(p[b])
int fx=r_find(a),fy=r_find(p[b]);
f[fx]=fy;
p[a]=b,p[b]=a; //存储敌人
int ans=0;
for(int i=1;i<=n;i++)
if(f[i]==i) ans++;
cout<<ans<<endl;
return 0;
P1955 [NOI2015] 程序自动分析
离散化处理+并查集。。。。思路是不难,但这离散化处理确实麻烦
1.进行排序,然后去重。
2.lowerbound进行下标的查找
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
int f[maxn],book[maxn*3],n,m;
struct node
int x,y,z;
e[maxn];
bool cmp(node e1,node e2)
return e1.z>e2.z;
int r_find(int r)
if(f[r]==r)
return r;
f[r]=r_find(f[r]);
return f[r];
signed main()
int t;cin>>t;
while(t--)
int tol=0;cin>>n;
memset(book,0,sizeof(book));
for(int i=1;i<=n;i++)
cin>>e[i].x>>e[i].y>>e[i].z;
book[++tol]=e[i].x,book[++tol]=e[i].y;
sort(book+1,book+tol+1);
int cnt=unique(book+1,book+tol+1)-book-1;
for(int i=1;i<=n;i++)
e[i].x=lower_bound(book+1,book+cnt+1,e[i].x)-book;
e[i].y=lower_bound(book+1,book+cnt+1,e[i].y)-book;
for(int i=1;i<=cnt;i++) f[i]=i;
int flag=1;
sort(e+1,e+n+1,cmp);
for(int i=1;i<=n;i++)
int fx=r_find(e[i].x),fy=r_find(e[i].y);
if(e[i].z==1)
f[fx]=fy;
else if(e[i].z==0)
if(fx==fy)
cout<<"NO"<<endl;flag=0;break;
if(flag)
cout<<"YES"<<endl;
return 0;
P1991 无线通讯网
主要是对于电话的处理。共p个灯塔,需要p-1条边,最后的(s-1)个边放电话。
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
int f[maxn],s,p,a[maxn],b[maxn],cnt;
struct node
int x,y;double dis;
e[maxn];
bool cmp(node e1,node e2)
return e1.dis<e2.dis;
int r_find(int r)
if(f[r]==r)
return r;
f[r]=r_find(f[r]);
return f[r];
double cal(int x1,int y1,int x2,int y2)
return (double)sqrt((x1-x2)*(x1-x2)*1.0+(y1-y2)*(y1-y2)*1.0);
signed main()
scanf("%d%d",&s,&p);
for(int i=1;i<=p;i++)
scanf("%d%d",&a[i],&b[i]);
for(int i=1;i<p;i++)
for(int j=i+1;j<=p;j++)
e[++cnt].x=i,e[cnt].y=j,e[cnt].dis=cal(a[i],b[i],a[j],b[j]);
sort(e+1,e+cnt+1,cmp);
for(int i=1;i<=p;i++) f[i]=i;
int ans=0;
for(int i=1;i<=cnt;i++)
int fx=r_find(e[i].x),fy=r_find(e[i].y);
if(fx!=fy)
f[fx]=fy;ans++;
if(ans>=(p-1)-(s-1))
ans=i;break;
cout<<fixed<<setprecision(2)<<e[ans].dis<<endl;
return 0;
背包
举例:10000个物品利用二进制优化,拆分成1,2,4,8,16,32,64,128……个,剩下的不满则10000去减。
int t=1;
while(x>=t)
v[cnt]=a*t;
c[cnt++]=b*t;
x-=t;t<<=1;
if(x)
v[cnt]=a*x;
b[cnt++]=b*x;
P2170 选学霸
难点在于背包的处理。
记得学一下bitset优化的01背包!!!
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
int f[maxn],n,m,k,sz[maxn],p[maxn],cnt,dp[maxn];
int r_find(int r)
if(f[r]==r)
return r;
f[r]=r_find(f[r]);
sz[r]=sz[f[r]];
return f[r];
signed main()
cin>>n>>m>>k;
for(int i=1;i<=n;i++) f[i]=i,sz[i]=1;
for(int i=1;i<=k;i++)
int a,b;cin>>a>>b;
int fx=r_find(a),fy=r_find(b);
if(fx!=fy)
f[fx]=fy;
sz[fx]+=sz[fy];
sz[fy]=sz[fx];
for(int i=1;i<=n;i++)
if(f[i]==i)
p[++cnt]=sz[i];
dp[0]=true;
for(int i=1; i<=cnt; i++)
for(int j=n; j>=p[i]; j--)
if(!dp[j]&&dp[j-p[i]])
dp[j]=true;
int ans=inf,minn=inf;
for(int i=0; i<=n; i++)
if(dp[i]&&abs(i-m)<minn) minn=abs(i-m),ans=i;
cout<<ans<<endl;
return 0;
以上是关于3/25《并查集》的主要内容,如果未能解决你的问题,请参考以下文章