hdu3590 - 树的删边游戏+anti-sg

本文详细解析了HDU3590问题的解决方案,利用SG定理计算树状结构中各节点的SG值。通过深度优先搜索(DFS)遍历树结构,确保了每个节点的SG值正确计算,特别注意了边的双向性以避免错误。最终,文章提供了完整的代码实现。

hdu3590

思路:

定理:叶子节点的sg值为0,中间节点的sg值为它的所有子节点的sg值加1后的异或和

这样写个dfs就可以很轻松的求解,我wa了两发,是因为建树的时候出错了,只建了单向的,比如说他给你的点对是(2,5)但实际上2是5的孩子,这样的话我们建(2,5)不就建错了,应该(5,2),所以我们加边的时候应该加双向边,dfs的时候设一个父节点,不让其反向走就可以了~

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
#include<string>
#include<cstring>
#define ll long long
using namespace std;

const int N=105;
struct pro{int to,next;};
pro edge[2*N];
int head[N],cnt;

void addEdge(int from,int to){
    edge[cnt].to=to;
    edge[cnt].next=head[from];
    head[from]=cnt++;
}

int get_sg(int x,int pre){
    int res=0;
    for(int i=head[x];i!=-1;i=edge[i].next){
        int dot=edge[i].to;
        if(dot==pre)continue;
        res^=(1+get_sg(dot,x));
    }
    return res;
}

void init(){
    memset(head,-1,sizeof(head));
    memset(edge,0,sizeof(edge));
    cnt=0;
}

int main(){
    int n,m,a,b;
    while(scanf("%d",&n)!=EOF){//n棵树
        int ans=0,flag=0;
        while(n--){
            scanf("%d",&m);//第i棵数有m个点
            init();
            for(int j=1;j<m;j++){
                scanf("%d%d",&a,&b);
                addEdge(a,b);
                addEdge(b,a);
            }
            int t1=get_sg(1,0);
            ans^=t1;
            if(t1>1)flag=1;
        }
        if((ans&&flag)||(!ans&&!flag))printf("PP\n");
        else printf("QQ\n");
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值