随笔 - 164  文章 - 0  评论 - 4  阅读 - 9771

2023ACM暑假训练day 1 最小生成树

DAY 1 最小生成树

训练地址:传送门

训练简介

2023-06-26
早上:ABCDJKLM
下午:EFH
晚上:G
发现早上都是kruskal,下午都是prim
这次训练板子题为主
后补 I 题 最小生成树的唯一性

7.12小整理,有时间再做一遍+整理[ ]

A 题

百炼oj 1251:Jungle Roads
题意:

思路:
...老长的英文题面,阿巴阿巴,慢慢看就知道,就是一道最小生成树板子题
村庄数不多,kruskal算法即可

//>>>Qiansui
#include<map>
#include<set>
#include<list>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<string>
#include<vector>
#include<utility>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<functional>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x,y,sizeof(x))
//#define int long long
// typedef std::pair<int,int> pii;
// typedef std::pair<ll,ll> pll;
// typedef std::pair<ull,ull> pull;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
return x*f;
}
using namespace std;
const int maxm=200+5,inf=0x3f3f3f3f,mod=998244353;
int n,k,fa[maxm],ans;
void pre(int x){
ans=0;
for(int i=0;i<=x;++i){
fa[i]=i;
}
return ;
}
int findfa(int x){
if(fa[x]==x) return x;
else return fa[x]=findfa(fa[x]);
}
struct node{
int u,v,w;
bool operator <(const node& a)const{
return a.w<w;
}
};
void solve(){
while(cin>>n){
if(n==0) break;
pre(n+130);
char ch,ver;
int cs,w,v,u;
node t;
priority_queue<node> q;
for(int i=0;i<n-1;++i){
cin>>ch>>cs;
while(cs--){
cin>>ver>>w;
t.u=ch;
t.v=ver;
t.w=w;
q.push(t);
}
}
while(!q.empty()){
t=q.top();
q.pop();
u=findfa(t.u);
v=findfa(t.v);
if(u!=v){
ans+=t.w;
fa[u]=v;
}
}
cout<<ans<<'\n';
}
return ;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _=1;
// cin>>_;
while(_--){
solve();
}
return 0;
}

B 题

最小生成树简单题

C 题

代码写错了

int u=findfa(i),v=findfa(j);
fa[u]=v;//wa原因:这里之前的提交写错了!!!

D 题

哪来的多输入啊。。。

J 题

。。。题目古怪的输出,固然是不用的。。。
不知道怎么评价

Huge input, scanf is recommended.
这句话只是给你看的,不需要输出。。。

L 题

偷了个dsu的板子

struct dsu{
int n;
vector<int> fa;
dsu(int x):n(x),fa(n+1){
for(int i=0;i<=x;++i) fa[i]=i;
}
int findfa(int x){
return fa[x]==x?x:fa[x]=findfa(fa[x]);
}
void merge(int u,int v){
int x=findfa(u),y=findfa(v);
fa[x]=y;
return ;
}
};

M 题

与D题同题不同源,一个是poj,一个是hdu

E 题

题意有点没读懂。。。
百度看一下题意吧
暴露问题:prim算法的具体实现还需要再练习一下

参考资料:
https://www.cnblogs.com/J-william/p/6371718.html

F 题

依旧是prim算法的运用,后面找个时间,利用优先队列来写prim算法
prim模板题

H 题

及其水的一题

abc307个人训练

C题大模拟。。。不知道错在什么地方了,没有再仔细看
我觉得可能自己题目都看错了。。。
有时间再回顾一下

E题圆环染色问题,有个结论,见自己的博客
也可以用DP?可以看看

G 题

最小生成树简单题
还需输出建造的边,可以看看

I 题 判断最小生成树是否唯一

题意:
判断最小生成树是否唯一
思路:
考虑最小生成树的唯一性。如果一条边 不在最小生成树的边集中,并且可以替换与其 权值相同、并且在最小生成树边集 的另一条边。那么,这个最小生成树就是不唯一的。

对于 Kruskal 算法,只要计算为当前权值的边可以放几条,实际放了几条,如果这两个值不一样,那么就说明这几条边与之前的边产生了一个环(这个环中至少有两条当前权值的边,否则根据并查集,这条边是不能放的),即最小生成树不唯一。

下为代码:

//>>>Qiansui
#include<map>
#include<set>
#include<list>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<string>
#include<vector>
#include<utility>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<functional>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x,y,sizeof(x))
//#define int long long
// typedef std::pair<int,int> pii;
// typedef std::pair<ll,ll> pll;
// typedef std::pair<ull,ull> pull;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
return x*f;
}
using namespace std;
const int maxm=1e4+5,inf=0x3f3f3f3f,mod=998244353;
int n,m,sum;
struct edge{
int u,v,w;
}p[maxm];
struct dsu{
int num;
vector<int> fa;
dsu(int x=maxm):num(x),fa(x+1){
for(int i=0;i<=x;++i) fa[i]=i;
}
int findfa(int x){ return fa[x]==x?x:findfa(fa[x]); }
void merge(int u,int v){
fa[findfa(u)]=findfa(v);
return ;
}
};
bool kruskal(){
bool f=false;
sort(p,p+m,[](edge x,edge y){
return x.w<y.w;
});
dsu ds(n);
for(int i=0;i<m;++i){
queue<edge> q;
int len=p[i].w;
while(i<m && len==p[i].w){
if(ds.findfa(p[i].u)!=ds.findfa(p[i].v))
q.push(p[i]);
++i;
}
--i;
while(!q.empty()){
edge t=q.front();
q.pop();
if(ds.findfa(t.u)!=ds.findfa(t.v)){
sum+=t.w;
ds.merge(t.u,t.v);
}else{
return true;
}
}
}
return f;
}
void solve(){
cin>>n>>m;
for(int i=0;i<m;++i){
cin>>p[i].u>>p[i].v>>p[i].w;
}
sum=0;
if(kruskal()) cout<<"Not Unique!\n";
else cout<<sum<<'\n';
return ;
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int _=1;
cin>>_;
while(_--){
solve();
}
return 0;
}
posted on   Qiansui  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示