Living-Dream 系列笔记 第33期
Living-Dream 系列笔记强势回归(雾)
T1
并查集妙妙题。
很容易想到一种朴素的贪心策略:
对于所以物品按照价格从大到小排序,
然后每一个物品,找到最晚的没有卖物品的那一天卖掉此物品。
这样贪心的时间复杂度为 \(O(\max d_i \times n)\),可以通过。
考虑如何优化此贪心。
可以发现朴素贪心时间复杂度的瓶颈
在于找到最晚的没有卖物品的那一天,
于是我们采用并查集,
每次卖出物品时将当前这一天与上一天合并,
然后每次在第 \(x\) 天查询 \(fa_x\) 即为所求。
时间复杂度是 \(O(n \log \max d_i)\) 的。
#include<bits/stdc++.h> using namespace std; int n,ans,maxi; pair<int,int> a[10031]; bool vis[10031]; int fa[10031]; bool cmp(pair<int,int> a,pair<int,int> b){ return a.first>b.first; } int fnd(int x){ return fa[x]==x?x:fa[x]=fnd(fa[x]); } int main(){ while(cin>>n){ ans=0,maxi=-1e9; for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second,maxi=max(maxi,a[i].second); sort(a+1,a+n+1,cmp); memset(vis,0,sizeof(vis)); for(int i=1;i<=maxi;i++) fa[i]=i; for(int i=1;i<=n;i++){ int pos=fnd(a[i].second); if(pos>0) ans+=a[i].first,fa[pos]=pos-1; } cout<<ans<<'\n'; } return 0; }
似乎还有一种堆做法,有心情再更。
upd:堆做法在本人的算法竞赛进阶指南笔记中有。
T2
最小生成树的板子。
最小生成树的定义:\(n\) 点 \(m\) 边的无向连通图中边权和最小的 \(n\) 点树。
如何求最小生成树:
-
\(\texttt{Kruskal}\)
-
\(\texttt{Prim}\)(暂未学习)
\(\texttt{Kruskal}\) 算法:
将 \(m\) 边按照边权从小到大排序,
然后对于两个节点,
若它们未联通(用并查集维护),
就对它们进行连边即可。
证明:(询问)。
#include<bits/stdc++.h> using namespace std; int n,m; int fa[200031]; struct E{ int u,v,w; }e[200031]; bool cmp(E x,E y){ return x.w<y.w; } int fnd(int x){ return fa[x]==x?x:fa[x]=fnd(fa[x]); } void mrg(int x,int y){ x=fnd(x),y=fnd(y); fa[x]=y; } int kruskal(){ int ans=0,cnt=0; for(int i=1;i<=m;i++){ if(fnd(e[i].u)!=fnd(e[i].v)){ mrg(e[i].u,e[i].v); ans+=e[i].w; cnt++; if(cnt==n-1) return ans; } } return -1; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w; sort(e+1,e+m+1,cmp); int Ans=kruskal(); if(Ans==-1) cout<<"orz"; else cout<<Ans; return 0; }
T3
大水题。
将答案累加改为答案取 \(\max\) 即可。
#include<bits/stdc++.h> using namespace std; int n,m; int fa[100031]; struct E{ int u,v,w; }e[100031]; bool cmp(E x,E y){ return x.w<y.w; } int fnd(int x){ return fa[x]==x?x:fa[x]=fnd(fa[x]); } void mrg(int x,int y){ x=fnd(x),y=fnd(y); fa[x]=y; } int kruskal(){ int ans=-1e9,cnt=0; for(int i=1;i<=m;i++){ if(fnd(e[i].u)!=fnd(e[i].v)){ mrg(e[i].u,e[i].v); ans=max(ans,e[i].w); cnt++; if(cnt==n-1) return ans; } } return -1; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w; sort(e+1,e+m+1,cmp); //if(Ans==-1) cout<<"orz"; cout<<kruskal(); return 0; }
T4
大水题 \(\times \ 2\)。
终止条件改为连通块数量为 \(k\) 即可。
#include<bits/stdc++.h> using namespace std; int n,m,k; int fa[200031]; struct E{ int u,v,w; }e[200031]; bool cmp(E x,E y){ return x.w<y.w; } int fnd(int x){ return fa[x]==x?x:fa[x]=fnd(fa[x]); } void mrg(int x,int y){ x=fnd(x),y=fnd(y); fa[x]=y; } bool check(){ int cnt=0; for(int i=1;i<=n;i++) if(fa[i]==i) cnt++; return cnt==k; } int kruskal(){ int ans=0; for(int i=1;i<=m;i++){ if(fnd(e[i].u)!=fnd(e[i].v)){ mrg(e[i].u,e[i].v); ans+=e[i].w; if(check()) return ans; } } return -1; } int main(){ cin>>n>>m>>k; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w; sort(e+1,e+m+1,cmp); int Ans=kruskal(); if(Ans==-1) cout<<"No Answer"; else cout<<Ans; return 0; }
习题 T1
大水题 \(\times \ 3\)。
将边权改为距离,端点改为下标,
终止条件改为 \(cnt=(s-1)-(p-1)=s-p\) 即可。
#include<bits/stdc++.h> using namespace std; int n,m,tot; map<int,int> fa; int x[531],y[531]; struct E{ int u,v; double w; }e[250031]; bool cmp(E x,E y){ return x.w<y.w; } double get_dis(int x,int y,int xx,int yy){ return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy)); } int c(int x){ int y=0; while(x) y++,x/=10; return y; } int fnd(int x){ return fa[x]==x?x:fa[x]=fnd(fa[x]); } void mrg(int x,int y){ x=fnd(x),y=fnd(y); fa[x]=y; } double kruskal(){ double ans=0; int cnt=0; for(int i=1;i<=tot;i++){ if(fnd(e[i].u)!=fnd(e[i].v)){ mrg(e[i].u,e[i].v); ans=e[i].w; cnt++; if(cnt==n-m) return ans; } } } int main(){ cin>>m>>n; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=n;i++) cin>>x[i]>>y[i]; for(int i=1;i<=n;i++) for(int j=1;j<i;j++) e[++tot].w=get_dis(x[i],y[i],x[j],y[j]), e[tot].u=i, e[tot].v=j; sort(e+1,e+tot+1,cmp); double Ans=kruskal(); cout<<setprecision(2)<<fixed<<Ans; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)