2023ACM暑假训练day 1 最小生成树
DAY 1 最小生成树
训练地址:传送门
训练简介
2023-06-26
早上:ABCDJKLM
下午:EFH
晚上:G
发现早上都是kruskal,下午都是prim
这次训练板子题为主
后补 I 题 最小生成树的唯一性
7.12小整理,有时间再做一遍+整理[ ]
A 题
思路:
...老长的英文题面,阿巴阿巴,慢慢看就知道,就是一道最小生成树板子题
村庄数不多,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; }
本文来自博客园,作者:Qiansui,转载请注明原文链接:https://www.cnblogs.com/Qiansui/p/17524390.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!