您的位置:首页 > 其它

【集训】jzoj 2017.7.5 noip模拟赛A 总结 (欧拉回路)

2017-07-05 19:35 211 查看
今天的比赛比较糟糕,只有第一题拿了暴力分。再次成为垫底选手。

主要是心态问题,第二三题没有尽力拿分。

先说第一题。

看到第一题就以为是异或方程组。但是这东西并不是唯一解,比赛基本就栽在这道题上了。 高斯消元还没学懂,自由元之类的东西还要再看。

正解是折半,我当时也想过,但是不知道怎么考虑互相之间的影响,其实两个状态异或起来就是了。想的不够多.

再说第二题

看起来像是个博弈。但仔细一想更像是DP?

一开始我设了f[i][j][0/1]来表示1..i的收益,但这是不对的。因为接下来的游戏进程会被当前选择所影响。

通俗一点说,就是这样DP走向了一条开始很少贡献,但后面贡献很大的路。然而实际上玩家2是不会也不可能这样走的,因为它绝顶聪明。

于是我们换一种想法,换成记忆化。

设f[i][j][0/1]是接下来游戏进程对玩家1的最大/最小贡献,将记忆化写成倒着Dp的形式。更新再加个小优化就可以过了。

第三题其实没怎么看过。连题目权值一点用都没有都没看到。因为权值是偶数,所以一定有一条欧拉回路(所有边走过且仅走过一次)。

然后问题就转为求从1开始的字典序最小的欧拉回路。

一种O(n2)的算法,从点1开始遍历,删掉走过的边,在退栈的时候加入答案。

void dfs(int x) {
for (int i=1; i<=n; i++) if (g[x][i]) {
--g[x][i]; --g[i][x];
dfs(i);
}
ans[++ans[0]]=x;
}


简略证明一下正确性。

1. 第一个没有的继续走的点一定是1.因为进一个点那么这个点的度数减1,又因为所有点的度数都是偶数(1点特殊),所以一定有一条出边。

2. 那么我们的算法可以视为在这个第一次绕完的环上扩展。对于一个点v,若有新环

v−>g1...g2−>v(g1<g2),则可以在原环上替换v为新环。注意要字典序最优秀,所以v需要在最后入队。最后将ans倒着输出。

3. 为什么要最后入队+倒着输出

首先如果不存在新环,那么在最后加入答案与最先加入答案是等价的。但有新环后最优的欧拉回路顺序应该是1,(v,g1,g2,v),1。与出栈顺序正好相反。画个图理解一下。

明天的比赛要注意:

1. 不死磕一题,

2. 思考时间控制在1h,

3. 先打暴力再打正解,

4. 记得多根据数据范围与问题想一下学过的算法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: