codeforces429A BFS

本文介绍了一种基于树形结构的变换算法,旨在通过最少的操作次数将树中节点的初始值转换为目标值。通过记录每个节点的变化次数并采用BFS遍历的方法,实现了高效的求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:给你一棵有n个节点的树,每个节点的value为0或1,给你初始value和目标value,对于每个节点课以执行一种操作:将该节点的value变为相反的即0变为1,1变为0,同时给节点的孙子节点,孙子节点的孙子都变反。问,最少进行多少次操作可以将初始value变为目标value,输出操作次数和需要更改的节点。

思路:记录每个节点需要变num1和不需要变num2的次数,那么他的儿子结点变不变可以由父节点的值得出。若进行了相应变换后与目标value不同,则进行一次操作,并更新num1和num2的值。进行一次BFS即可。


#include <algorithm>
#include <set>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <iostream>

using namespace std;

#define maxn 1000010
#define mem(a , b)  memset(a , b , sizeof(a))
#define LL long long

int a[110000] , b[110000];
int ans[110000];
int n;
vector<int>V[110000];
int vis[110000];
struct node
{
    int val;
    int num1;
    int num2;
}tmp , tmp2;

int main()
{
    int t;
    while(scanf("%d" , &n) != EOF)
    {
        mem(vis , 0);
        for(int i = 0 ; i <= n ; i ++) V[i].clear();
        int u ,v;
        for(int i = 0 ; i < n - 1  ; i ++)
        {
            scanf("%d %d" , &u , &v);
            V[u].push_back(v);
            V[v].push_back(u);
        }
        for(int i = 1 ; i <= n ; i ++) scanf("%d" , &a[i]);
        for(int i = 1 ; i <= n ; i ++) scanf("%d" , &b[i]);
        int pos = 0;
        queue<node>q;
        while(!q.empty()) q.pop();
        tmp.val = 1;
        tmp.num1 = tmp.num2 = 0;
        q.push(tmp);
        vis[1] = 1;

        while(!q.empty())
        {
            tmp = q.front();
            q.pop();
            if(a[tmp.val] == b[tmp.val])
            {
                int len = V[tmp.val].size();
                for(int i = 0 ; i < len ; i ++)
                {
                    if(vis[V[tmp.val][i]]) continue;
                    tmp2.val = V[tmp.val][i];
                    tmp2.num1 = tmp.num2;
                    tmp2.num2 = tmp.num1;
                    if(tmp2.num1 % 2)
                    {
                        if(a[tmp2.val] == 0 ) a[tmp2.val] = 1;
                        else a[tmp2.val] = 0;
                    }
                    q.push(tmp2);
                    vis[tmp2.val] = 1;
                }
            }
            else
            {
                ans[pos++] = tmp.val;
                a[tmp.val] = b[tmp.val];
                int len = V[tmp.val].size();
                for(int i = 0 ; i < len ; i ++)
                {
                    if(vis[V[tmp.val][i]]) continue;
                    tmp2.val = V[tmp.val][i];
                    tmp2.num1 = tmp.num2 ;
                    tmp2.num2 = tmp.num1 + 1;
                    if(tmp2.num1 % 2)
                    {
                        if(a[tmp2.val] == 0 ) a[tmp2.val] = 1;
                        else a[tmp2.val] = 0;
                    }
                    q.push(tmp2);
                    vis[tmp2.val] = 1;
                }
            }
        }
        cout << pos << endl;
        //sort(ans , ans + pos);
        for(int i = 0 ; i < pos ; i ++)
        {
            printf("%d\n" , ans[i]);
        }
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值