「算法笔记」无向图删边游戏

一、树的删边游戏

给出一棵有根树,两人轮流操作,每人每次可以选择一条边删去,不与根节点相连的部分将被移走。无法操作者输。

结论:叶子节点的 \(\text{SG}\) 值为 \(0\);中间节点的 \(\text{SG}\) 值为它的所有子节点的「\(\text{SG}\) 值加 \(1\)」的异或和。这样就可以推出根节点的 \(\text{SG}\) 值。证明

二、POJ 3710 Christmas Game

Description

有 \(n\) 个局部连通的图,两人轮流操作,每人每次可以选择一条边删去,不与根节点相连的部分将被移走。无法操作者输。(图是通过从基础树上加一些边得到的,环与环之间无公共边,且只与基础树有一个公共点。)

Solution

与「树的删边游戏」不同的在于图中 出现了环。所以环可以单独考虑。

分析环的性质:环保证不共用边,且只与基础树有一个公共点。因此所有的环都是从树中某一个点连出又连回同一个点的简单环。

  • 对于长度为奇数的环,去掉其中任意一条边后,剩下的两个链长度 同奇偶,异或之后的 \(\text{SG}\) 值不可能为奇数,并且可能为 \(0\)。所以进行 \(\text{mex}\) 运算后它的 \(\text{SG}\) 值为 \(1\)
  • 对于长度为奇数的环,去掉其中任意一条边后,剩下的两个链长度 不同奇偶,异或之后的 \(\text{SG}\) 值不可能为 \(0\)。所以进行 \(\text{mex}\) 运算后它的 \(\text{SG}\) 值为 \(0\)。实际上它并没有贡献。

所以可以去掉所有的偶环,将所有的奇环变为长度为 \(1\) 的链,转化为「树的删边游戏」的模型。

算出每一棵树的 \(\text{SG}\) 值,再把所有根节点的 \(\text{SG}\) 值异或起来即可。

具体实现时,不需要做「将所有的奇环变为长度为 \(1\) 的链」的操作,只需考虑奇环的贡献。

#include<cstdio>
#define int long long
using namespace std;
const int N=1e5+5;
int t,n,m,x,y,cnt,hd[N],to[N<<1],nxt[N<<1],top,s[N],sg[N],vis[N],ans;    //vis=0: 未访问过  vis=1: 访问过且不是某个环上的点(不考虑树上的点)  vis=-1: 访问过且是某个环上的点 
void add(int x,int y){
    to[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt;
}
void dfs(int x,int fa){
    s[++top]=x,vis[x]=1,sg[x]=0;
    bool flag=0;
    for(int i=hd[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa&&!flag){flag=1;continue;}     //第一次连向父节点 
        if(vis[y]==1){
            int cnt=1,now=x;
            while(now!=y) cnt++,vis[now]=-1,now=s[--top];
            if(cnt&1) sg[y]^=1;    //奇环 
        }
        else if(!vis[y]){
            dfs(y,x);
            if(~vis[y]) sg[x]^=(sg[y]+1);    //不在环上的才能更新 
        }
    }
    if(~vis[x]) --top;    //非环上的,及时出栈 
}
signed main(){
    while(~scanf("%lld",&t)){
        ans=0;
        while(t--){
            scanf("%lld%lld",&n,&m),cnt=top=0;
            for(int i=1;i<=n;i++) hd[i]=vis[i]=0;
            for(int i=1;i<=m;i++){
                scanf("%lld%lld",&x,&y);
                add(x,y),add(y,x);
            }
            dfs(1,0),ans^=sg[1];    //根节点的 SG 值异或起来 
        }
        puts(ans?"Sally":"Harry");
    }
    return 0;
}

三、图的删边游戏

「POJ3710 Christmas Game」去掉环的限制。即:给定一个无向连通图,有一个点作为图的根。两人轮流操作,每人每次可以从图中选择一条边删去,不与根节点相连的部分将被移走。无法操作者输。

对于这个模型,有一个定理——Fusion Principle。

结论:对无向图做如下改动:将图中的任意一个偶环缩成一个新点,任意一个奇环缩成一个新点加一条新边;所有连到原先环上的边全部改为与新点相连。这样的改动不会影响图的 \(\text{SG}\) 值。

因此可以将任意一个无向图改成树结构。然后就能把「图的删边游戏」转化为「树的删边游戏」了。

四、参考资料

posted @ 2020-12-21 18:28  maoyiting  阅读(1144)  评论(0编辑  收藏  举报