[题解]ABC282E Choose Two and Eat One

ABC282E Choose Two and Eat One

又一个图论的回顾——Kruskal最小(最大)生成树算法。

看到\(n\)的范围只有\(500\),应该没有什么特别的算法。那么我们考虑建一个*\(n\)个顶点的完全图,节点\(x\)到节点\(y\)的边权值就是\(x^y+y^x\)。然后跑一遍最大生成树,得到的和就是最大结果了。

如何证明生成树的边一定满足题目条件?因为一共要吃掉\(n-1\)个球,也就是删除图上的\(n-1\)条边,若想让这\(n-1\)条边连接\(n\)个点,必须要求这些边构成一个树。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct edge{
int u,v,w;
}edges[250010];
int n,m,a[510],fa[510],cnt;
bool cmp(edge a,edge b){return a.w>b.w;}
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
int qpow(int a,int b){
int fac=1;
while(b){
if(b&1) fac=(fac*a)%m;
a=(a*a)%m,b>>=1;
}
return fac;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
edges[++cnt].u=i,edges[cnt].v=j;
edges[cnt].w=(qpow(a[i],a[j])+qpow(a[j],a[i]))%m;
}
}
sort(edges+1,edges+1+cnt,cmp);
for(int i=1;i<=n;i++) fa[i]=i;
int edgecnt=0,ans=0;
for(int i=1;i<=cnt;i++){
int u=find(edges[i].u),v=find(edges[i].v);
if(u==v) continue;
fa[u]=v;
edgecnt++;
ans+=edges[i].w;
if(edgecnt>=n-1) break;
}
cout<<ans;
return 0;
}
posted @   Sinktank  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2025-3-6 6:10:43 TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2024 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.
点击右上角即可分享
微信分享提示