第七届河南省ACM大学生程序设计大赛 G.Code The Tree

题目等网上更新出来了再贴吧

记得我看这个题挺早的,但当时压根就没看懂

我觉得这也是我的一个问题:太着急

刚开始总想找一道简单易懂的水题,这种思路是对的,但是再找的过程中也要试着去认真理解题意

做这个题的时候我们就只剩最后一个小时了

趁着峻峥出去尿尿的时候我认真读题,总算把题目给读懂了

就是给你一棵树,每次找到度数为1的节点中节点权值最小的,输出其出度所对应节点的权值

一直重复这个过程即可

这个题其实就是一个图,如果想着建树那就大错特错了

我的想法就是建图的同时记录每个节点的度数,每次取度数为1的节点中最小权值对应节点输出相应节点权值即可

说实话知道题意就是很水的一个题了,结果我们调了40+分钟,导致最后交题的时候就只剩几分钟了

看到AC的时候我们三个(我,峻峥,小明)真的异口同声的叫了出来

代码如下:

#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 1010
#define ll long long
using namespace std;

char str[MAXN];
int map[MAXN][MAXN];
int ct[55];//用来记录节点i的度数
int ret[55];//用来保存最后的结果
stack<int> s;

int main(void) {
    while(gets(str)) {
        int num = 0;
        memset(map, 0, sizeof(map));
        int len = strlen(str);
        for(int i=0; i<len; ++i) {
            if(str[i] == '(') {
                int d;
                ++num;
                sscanf(str+i+1, "%d", &d);
                //交题的时候一直WA,原因就是原来进栈的方式是str[i]-'0',这明显只能处理一位字符
                //峻峥改成这样我们就过了,我觉得这个方法很值得借鉴,如果当时只有我一个的话估计就跪了
                s.push(d);
            }
            else if(str[i] == ')') {
                int top1 = s.top();
                s.pop();
                if(s.size() == 0)
                    continue;
                int top2 = s.top();
                map[top2][top1] = 1;
                map[top1][top2] = 1;
                ++ct[top1];
                ++ct[top2];
            }
        }
        int k = 0;
        int tnum = num;
        while(1) {//之所以有这个循环是要保证每次都要从小数字向大数字遍历,
            //不然对于第一个样例最后的8不会输出,因为最后只剩两个节点2 8,而此时遍历到8所以会输出2
            //我们队就因为这个问题一直在调!!
            if(num == 1)
                break;
            int flag = 0;
            for(int i=1; i<=tnum; ++i) {
                if(ct[i] == 1) {
                    for(int j=1; j<=tnum; ++j) {
                        if(map[i][j] == 1) {
                            ret[k++] = j;
                            --ct[i];
                            --ct[j];
                            map[i][j] = map[j][i] = 0;
                            flag = 1;
                            num--;
                            break;
                        }
                    }
                    if(flag == 1)
                        break;
                }
                if(flag == 1)
                    break;
            }
        }
        printf("%d", ret[0]);
        for(int i=1; i<k; ++i) {
            printf(" %d", ret[i]);
        }
        printf("\n");
    }

    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值