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

浙公网安备 33010602011771号