UVa10672 - Marbles on a tree(BFS)

本文探讨了一种解决在有根树结构中,通过移动物品以确保每个节点恰好包含一个物品的最短步骤数的问题。通过使用两个数组来跟踪节点的父节点和出度,该算法首先将所有出度为0的节点(叶子节点)加入队列。然后,从队列中取出节点,尝试将其物品移动到父节点或从父节点接收物品,直到每个节点都恰好有一个物品为止。
摘要由CSDN通过智能技术生成

n boxes are placed on the vertices of a rooted tree, which are numbered from 1 to n, 1 ≤ n ≤ 10000. Each box is either empty or contains a number of marbles; the total number of marbles is n.

The task is to move the marbles such that each box contains exactly one marble. This is to be accomplished be a sequence of moves; each move consists of moving one marble to a box at an adjacent vertex. What is the minimum number of moves required to achieve the goal?

The input contains a number of cases. Each case starts with the number n followed by n lines. Each line contains at least three numbers which are: v the number of a vertex, followed by the number of marbles originally placed at vertex v followed by a number d which is the number of children of v, followed by d numbers giving the identities of the children of v.

The input is terminated by a case where n = 0 and this case should not be processed.

For each case in the input, output the smallest number of moves of marbles resulting in one marble at each vertex of the tree.

Sample input

 
9
1 2 3 2 3 4
2 1 0
3 0 2 5 6
4 1 3 7 8 9
5 3 0
6 0 0
7 0 0
8 2 0
9 0 0
9
1 0 3 2 3 4
2 0 0
3 0 2 5 6
4 9 3 7 8 9
5 0 0
6 0 0
7 0 0
8 0 0
9 0 0
9
1 0 3 2 3 4
2 9 0
3 0 2 5 6
4 0 3 7 8 9
5 0 0
6 0 0
7 0 0
8 0 0
9 0 0
0

Output for sample input

7
14
20
题意:由n个结点组成的有根树,每个结点中可能没有marble,也可能有,各个结点的marble总数为n。每次只能将一个marble移动到相邻的结点,使得每个结点上都有一个marble,求最少的移动次数

思路:用两个数组,一个统计结点的父结点,另一个数组统计结点的出度。先将出度为0的结点(即叶子结点)放入队列,从队列中取出一个结点,要么将marble移到父结点,只留下一个marble,要么从父结点移一个marble到当前结点,同时将父结点的出度减1。如果父结点的出度为0,将父结点也放入队列

#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>

using namespace std;

const int MAXN = 10010;

int p[MAXN], outDegree[MAXN];
int marble[MAXN];
int n;

bool input()
{
    scanf("%d", &n);
    if (n == 0) return false;
    
    memset(outDegree, 0x00, sizeof(outDegree));
    memset(p, 0x00, sizeof(p));
    
    for (int i = 0; i < n; i++) {
        int v, numMarble, d;
        scanf("%d%d%d", &v, &numMarble, &d);
        outDegree[v] = d;
        marble[v] = numMarble;
        for (int j = 0; j < d; j++) {
            int child;
            scanf("%d", &child);
            p[child] = v;
        }
    }
    return true;
}

void solve()
{
    queue<int> q;
    
    for (int i = 1; i <= n; i++) {
        if (outDegree[i] == 0) q.push(i);
    }
    
    int ans = 0;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        int parent = p[u];
        if (parent == 0) break;
        if (marble[u] != 1) {
            marble[parent] += marble[u] - 1;
            ans += abs(marble[u] - 1);
            marble[u] = 1;
        } 
        
        outDegree[parent]--;
        if (outDegree[parent] == 0) q.push(parent);
    }
    
    printf("%d\n", ans);
}

int main(int argc, char **argv) 
{
#ifndef ONLINE_JUDGE
    freopen("d:\\OJ\\uva_in.txt", "r", stdin);
#endif
 
    
    while (input()) {
        solve();
    }
    
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值