PDD----配对堆

//洛谷P3377,不会配对堆基本思路的请百度
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; struct heap { int fa; vector<int>son; int val; }PDD[100010];
//每个节点存父亲fa(好像没用),儿子son,权值val
int fa[100010]; int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
//用并查集维护每个点在哪个堆里
int flag[100010];//每个点有没有被删除 int merge(int a,int b) { a=find(a);b=find(b); if(a==b) return a; if(a>b) swap(a,b); if(PDD[a].val>PDD[b].val) {fa[a]=b;PDD[a].fa=b;PDD[b].son.push_back(a);return b;} else {fa[b]=a;PDD[b].fa=a;PDD[a].son.push_back(b);return a;} }//找出两个元素所在堆的堆顶,合并 void del(int x) { if(flag[x]) {printf("-1\n");return;}//如果被删了,直接退出 x=find(x); flag[x]=1; printf("%d\n",PDD[x].val); queue<int>s; int cnt=0;//cnt记录有几个儿子 for(int i=0;i<PDD[x].son.size();i++) { int t=PDD[x].son[i]; PDD[t].fa=t; fa[t]=t;//重置并查集信息(分离点) s.push(t); ++cnt; } if(cnt==0) { PDD[x].fa=0; fa[x]=0; return; } while(cnt>1) { int a=s.front();s.pop(); int b=s.front();s.pop(); s.push(merge(a,b)); --cnt; } int top=s.front();//剩下的就是新根节点 PDD[x].fa=top; fa[x]=top; PDD[x].son.clear();
//将被删节点fa设为新根,防止路径压缩错误 }
int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&PDD[i].val); PDD[i].fa=i; fa[i]=i; } for(int i=1;i<=m;i++) { int id; scanf("%d",&id); if(id==1) { int x,y; scanf("%d%d",&x,&y); if(flag[x]==0&&flag[y]==0)merge(x,y); } if(id==2) { int x; scanf("%d",&x); del(x); } } }

 

转载于:https://www.cnblogs.com/wjxgy/p/7774690.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值