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

今天的比赛比较糟糕,只有第一题拿了暴力分。再次成为垫底选手。
主要是心态问题,第二三题没有尽力拿分。

先说第一题。
看到第一题就以为是异或方程组。但是这东西并不是唯一解,比赛基本就栽在这道题上了。 高斯消元还没学懂,自由元之类的东西还要再看。
正解是折半,我当时也想过,但是不知道怎么考虑互相之间的影响,其实两个状态异或起来就是了。想的不够多.

再说第二题
看起来像是个博弈。但仔细一想更像是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. 记得多根据数据范围与问题想一下学过的算法。

你可能感兴趣的:(总结)