题解:AT_abc352_e [ABC352E] Clique Connect
思路
考虑第一问(连通性),显然要使用并查集(下文的代码中使用了 bfs)。
但是我们显然不能将所有边都建出来。
因为只考虑连通性,所以只需保证一个集合内所选的边能保证所有点之间互相连通即可。
再考虑第二问(最小生成树)。
注意:下文中的
肯定不能建完图,但是我们知道,连接
正确性证明:
在我们进行 kruskal 时,我们是先对边长进行排序,然后判断两个端点是否连通。
现在在一个集合中,每一条边边长都一样,那么它们一定会排在一起。
现在我们选择了
为了不浪费我们的时间资源和空间资源,我们只需任意选择
代码实现
- 因为如果第一问使用并查集维护本题要写
个并查集,所以我第一问使用了 bfs 的方法判断连通。 - 因为要判断图的连通,所以只应进行
次 bfs。 union
在 C++ 中为关键字,所以并查集的合并操作我使用了vnion
。- 本题数据范围可能爆
int
。
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k[400005],c[400005],a[400005],vis[400005],fa[400005];
queue<int>q;
struct node{
int u,v,w,nxt;
}e[800005];
int head[400005],cnt;
void bfs(int now){
q.push(now);
while(!q.empty()){
int v=q.front();q.pop();
if(vis[v])continue;
vis[v]=1;
for(int i=head[v];i;i=e[i].nxt){
q.push(e[i].v);
}
}
}
bool cmp(node _,node __){
if(_.w<__.w)return 1;
return 0;
}
int findd(int now){
if(fa[now]==now)return now;
return fa[now]=findd(fa[now]);
}
void vnion(int _,int __){
fa[findd(__)]=findd(_);
}
void add(int u,int v,int w){
e[++cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].nxt=head[u];
head[u]=cnt;
}
int tot=0;
signed main(){
cin>>n>>m;
for(int i=1;i<=400004;i++)fa[i]=i;
for(int i=1;i<=m;i++){
cin>>k[i]>>c[i];
for(int j=1;j<=k[i];j++){
cin>>a[j];
}
for(int j=2;j<=k[i];j++){
add(a[1],a[j],c[i]);
add(a[j],a[1],c[i]);
}
}
bfs(1);
for(int i=1;i<=n;i++){
if(vis[i]==0){
cout<<-1;
return 0;
}
}
sort(e+1,e+cnt+1,cmp);
long long ans=0;
for(int i=1;i<=cnt;i++){
if(findd(e[i].u)!=findd(e[i].v)){
vnion(e[i].u,e[i].v);
ans+=e[i].w;
tot++;
}
if(tot==n-1)break;
}
cout<<ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】