牛客网算法竞赛难题
闲的没事参加了一下牛客网的算法训练赛
才发现这么难(划掉
才发现我对时间和空间复杂度的运算能力这么差
其中有一道题我的代码超过了空间限制
而另外一个人的没有。。。
还AC了
但是对比我们两个的代码我发现
好像开的数组一样大,我甚至还把一个数组换成了vector,但是还是内存爆掉了
搞不清为什么
原题如下:
糖果
题目描述:
在一个幼儿园里面有n\mathit nn个小朋友,分别编号1,2,...,n\text 1,2,...,n1,2,...,n。在这些小朋友中有一些小朋友互为朋友关系,总共有m\mathit mm对朋友。
作为幼儿园老师,你想买一些糖果分给小朋友,你知道第i\mathit ii个小朋友想要至少aia_{i}ai个糖果,否则他就会不开心。
同时,如果一个小朋友得到的糖果数小于他某个朋友得到的糖果数,他也会不开心。
请问你最少买多少糖果才能保证每个小朋友都不会不开心呢?
链接:https://ac.nowcoder.com/acm/contest/9983/G
来源:牛客网
输入描述:
第一行以空格分隔的两个整数n,m
第二行以空格分隔的n个正整数ai。
接下来m行每行以空格分隔的两个正整数u,v,代表u是v的朋友,v是u的朋友。
输出描述:
购买的最少糖果数以保证每个小朋友都不会不开心。
输入
3 1 1 2 3 1 2
输出
7说明
给第三个小朋友买3个糖果,前两个小朋友都买2两个糖果,总共至少买7个糖果。注意如果给第一个小朋友只买了1个糖果,那么他在看到自己的好朋友2有2个糖果的情况下,他就会不开心。
这道题题面上没有说朋友的朋友就是自己朋友
但也不难分析出来
假如A是B的朋友,c是B的朋友
A想要2颗糖,B想要3颗,C想要五颗
为了让C开心,C会得到5颗糖
为了让B开心,B也会得到五颗,因为B是C的朋友,当ta瞅瞅C手中的五颗糖和自己手中的三颗糖时,会很不开心
同理,为了让A开心,也给A五颗糖
A得到的糖数量与C相等
所以说这道题有考到并查集
那么我的代码是这样的:
1 #include <bits/stdc++.h> 2 #include <vector> 3 using namespace std; 4 int n,m,a,b,sum[1000005],head[1000005],ww; 5 vector <int> w; 6 long long ans;//经过计算,我认为ans的值可能会超过int类型 7 int find(int x){//寻找两拨孩子的头目 8 if(head[x]!=x) 9 head[x]=find(x); 10 return head[x]; 11 } 12 void hb(int x,int y){//把两拨孩子合并 13 int xx=find(x); 14 int yy=find(y); 15 head[yy]=xx; 16 } 17 int main(){ 18 w.push_back(0); 19 cin>>n>>m; 20 for(int i=1;i<=n;i++){ 21 head[i]=i;//初始化头领 22 sum[i]=1;//初始化队伍人数 23 } 24 for(int i=1;i<=n;i++){ 25 cin>>ww; 26 w.push_back(ww); 27 } 28 for(int i=1;i<=m;i++){ 29 cin>>a>>b; 30 if(find(a)!=find(b)){ 31 sum[find(a)]+=sum[find(b)];//把两拨人数相加 32 hb(a,b); 33 w[find(a)]=max(w[a],w[b]);//寻找这些人中,想要糖果最多的数量 34 } 35 } 36 for(int i=1;i<=n;i++){ 37 if(head[i]==i){//找到每队头领,代表该队即可; 38 ans+=sum[i]*w[i]; 39 } 40 } 41 cout<<ans; 42 return 0; 43 }
别人家的代码长这样(注释是根据我自己的理解写的,他才没那么善良:
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 int fa[1000005];//头目 6 inline int ff(int x)//相当于我代码里的find函数 7 { 8 if(fa[x]==x) return x; 9 return fa[x]=ff(fa[x]); 10 } 11 int mx[1000005],sz[1000005],a[1000005]; 12 int main(int argc, char** argv){ //main函数里加代码我还是第一次见,详情见博客https://blog.csdn.net/hopeneversleep/article/details/55798722 13 int n,m; 14 cin >> n >> m; 15 for(int i=1;i<=n;i++) fa[i]=i;//初始化头目 16 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 17 18 for(int i=1;i<=m;i++) 19 { 20 int u,v; 21 scanf("%d%d",&u,&v); 22 fa[ff(u)]=ff(v); //合并小组 23 } 24 for(int i=1;i<=n;i++) 25 { 26 mx[ff(i)]=max(mx[ff(i)],a[i]); 27 sz[ff(i)]++; 28 }//把小组里糖果最大需求量和小组人数单独统计 29 long long ans=0;//同样是long long 30 for(int i=1;i<=n;i++) ans+=(long long)sz[i]*mx[i]; 31 cout << ans; 32 return 0; 33 }