首页 > 代码库 > 51Nod 算法马拉松21(迎新年)

51Nod 算法马拉松21(迎新年)

技术分享

这次打算法马拉松是在星期五的晚上,发挥还算正常(废话,剩下的题都不会= =)。

讲讲比赛经过吧。

8:00准时发题,拿到之后第一时间开始读。

A配对,看上去像是二分图最大权匹配,一看范围吓傻了,先跳过读后面的题。

B完全二叉树的方差,大概看了一遍,好神的样子,跳过。

C多项式?好吧没学过FFT和NTT的我肯定不会,跳跳跳。

D最大值,哎呦这函数什么破玩意儿,看不懂,跳跳跳。

E B君的射击,卧槽毕克大人您出题就算了出这么一道码农题是要闹那样,跳跳跳。

F那些年,我们一起讲的故事,卧槽这特么简直就是道纯语文题,跳跳跳。

哎等等,跳没了……

好像A比较简单,先想想A算了……

第一思路是二分图最大权匹配,然后费用流暴力,一看数据范围这显然不靠谱,然后就开始思考问题的特殊性质。

不经意间按了几下F5,卧槽怎么你们做的那么快,看来是我想复杂了,这应该是个不太难的题。

想了想匹配的构造方法,贪心似乎不太可行,别的方法一时也想不出来,算了好像可以枚举每条边计算贡献……感觉像是对的,但是又对此深表怀疑……

中间又按了几次F5,卧槽你们做题怎么这么神速……看来这题确实简单,反正WA了也不会有惩罚,看我码一发枚举边计算贡献,随手一交,啊哈居然A了……

技术分享

自己交的比较早,所以是第18个A的(为什么我记得是第19个……还是说是第19个提交的……),排名还不错……(机房其他人好多都第几十+才A的……)

技术分享

看了看其他题,E题貌似之前看少了连通的圆可以使中间那块也变成洞,感觉自己并不会写。F题读了半天还是没读懂……D题的函数看懂了就是十进制位倒过来然后乱搞,然而还是没思路。C题也看了两眼,一看别人的运行时间都是十几ms,感觉像是O(1)的结论题,打了一发print input()(这是Python2)然而过不去样例……

然后开始搞B题,看见方差最小感觉像是一个三分平均数然后二分图最小权匹配,搞了半天搞出来新树直径的结论,然而并没有推出题解的神贪心,写了一发三分平均数+最小费用最大流(二分图最小权匹配),然后不知道哪儿写挂了,样例都过不去(也可能是函数根本不单峰……)……调了半天调不出来,狠狠心一交,1W19T,算了我弃疗……

技术分享

脑子昏昏涨涨,就此弃疗。星期六和星期天也没有再来做题,由于第一题交的早,最终成绩rank60,真是便宜我了。(然而排名太低,Rating往下掉了……= =)

技术分享

随便水水比赛就拿到了排名是20的倍数这个buff,话说运气真是好……

技术分享

技术分享

话说今天才收到点头盾,这速度我给差评……

给A题贴个题解:

既然要求匹配点的距离和最大,那么两条路径一定要尽可能相交(如果不相交,交换两条路径的端点不会变劣)。或者说,匹配路径一定要尽可能经过长的边。不过这还是不太好搞,所以放弃构造方法,考虑对每条边计算能出现在几条匹配路径中,也就是说能对答案产生多少贡献。

考虑一条长为w的边,设这条边连接的两个连通块的大小分别为a和b。为了保证距离和最大,我们需要使得尽量多的匹配路径经过这条边,所以应该尽量让边两端的点进行匹配,因此这条边最多经过min{a,b}次。

边与边之间互不影响(我不会证……),所以一遍dfs/bfs之后枚举每条边计算贡献即可。为了保险(防爆栈),我用的是bfs。

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 using namespace std;
 6 const int maxn=100010;
 7 struct edge{int u,v,w;}e[maxn];
 8 void bfs();
 9 vector<int>G[maxn];
10 int n,q[maxn],prt[maxn]={0},size[maxn]={0};
11 long long ans=0;
12 int main(){
13     scanf("%d",&n);
14     for(int i=1;i<n;i++){
15         scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
16         G[e[i].u].push_back(e[i].v);
17         G[e[i].v].push_back(e[i].u);
18     }
19     bfs();
20     for(int i=1;i<n;i++){
21         if(prt[e[i].u]==e[i].v)swap(e[i].u,e[i].v);
22         int s=min(size[e[i].v],size[1]-size[e[i].v]);
23         ans+=(long long)s*e[i].w;
24     }
25     printf("%lld",ans);
26     return 0;
27 }
28 void bfs(){
29     int head=0,tail=0;
30     q[tail++]=1;
31     while(head!=tail){
32         int x=q[head++];
33         size[x]=1;
34         for(int i=0;i<(int)G[x].size();i++)if(G[x][i]!=prt[x]){
35             prt[G[x][i]]=x;
36             q[tail++]=G[x][i];
37         }
38     }
39     for(int i=n;i;i--){
40         int x=q[i];
41         size[prt[x]]+=size[x];
42     }
43 }
View Code

附官方题解:

技术分享

(话说构造法真的可行嘛……我仍然理解不了贪心构造……只会写O(n2m2)的费用流……囧囧囧)

反思:

这次打比赛的时候有点着急,B题也没有耐心仔细想/写,发挥并不太好。

A题看见别人神速过题之后就有点慌了,一改求稳的作风,凭着直觉交了一份代码,能A估计是运气。今后的比赛或者是考试一定要求稳,毕竟无缘无故掉了几十分上百分可是很要命的。

 

下一站,UOJ Test Round #2。

加油。

51Nod 算法马拉松21(迎新年)