专栏文章

题解:AT_abc398_e [ABC398E] Tree Game

AT_abc398_e题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipu5jmt
此快照首次捕获于
2025/12/03 17:59
3 个月前
此快照最后确认于
2025/12/03 17:59
3 个月前
查看原文

E - Tree Game

题目大意

给定一棵有 NN 个节点的树,编号为 11NN。游戏玩家(你)和高桥君轮流向图中添加新的边 (i,j)(i,j),但只能添加不在图中已有边中出现、且不会形成奇环的边。当一位玩家无法进行有效操作时,该玩家失败。你的任务是决定先手或后手,并与高桥君交互,给出你的操作,直到获胜后结束游戏。

解题思路

用 BFS 为每个顶点染色,以区分出两个不交叠的颜色集合(把树看做二分图)。然后,对于颜色不同且尚未直接相连的一对节点 (i,j)(i, j),收集到集合 mm。若集合大小为奇数则先手,否则后手。随后在游戏循环中,两方轮流从 mm 中移除可行的一对节点并输出;对手的操作则从输入中读取并从 mm 中移除。
代码
CPP
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    
    int n;
    cin>>n;
    vector<vector<int>>g(n+1);
    vector<vector<bool>>e(n+1,vector<bool>(n+1,0));
    
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
        e[u][v]=e[v][u]=1;
    }

    vector<int>c(n+1,-1);
    queue<int>q;
    c[1]=0;
    q.push(1);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(auto v:g[u]){
            if(c[v]==-1){
                c[v]=c[u]^1;
                q.push(v);
            }
        }
    }

    set<pair<int,int>>m;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(c[i]!=c[j]&&!e[i][j]){
                m.insert({i,j});
            }
        }
    }
    
    bool f=(m.size()%2==1);
    if(f){
        cout<<"First\n";
        cout.flush();
    }
    else{
        cout<<"Second\n";
        cout.flush();
    }
    
    bool t=f;
    while(1){
        if(t){
            if(m.empty())break;
            auto p=*m.begin();
            m.erase(m.begin());
            cout<<p.first<<" "<<p.second<<"\n";
            cout.flush();
        }
        int u,v;
        cin>>u>>v;
        if(u==-1&&v==-1)break;
        pair<int,int>p=(u<v)?make_pair(u,v):make_pair(v,u);
        if(m.find(p)!=m.end()){
            m.erase(p);
        }
        t=1;
    }
    
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...