• POJ 2568/ZOJ 1965 Decode the Tree


    题意:在树中,每次删去节点值最小的叶子结点。    

      每删去一个点,就给出与这相连的点的值,直到最后只剩下一个根结点,给这N-1个数,重新建立这个树。

    思路:

      给出的节点号按次序存入到数组a中,将未给出的数存入到rest数组中去,并从小到大排序。      

      每次取一个给出的节点,那么我们需要求出与该点相连的被删去的点v。      

       而点v必定为 “不会在之后的数据中出现的值(即之后删除的叶子节点中再也没有与之相连的,即改点为叶子节点)” 和 “当前rest数组中最小的值”  中的最小值。      

      那么只要预处理一下,对于给出的节点号u,num[u][i]表示在给出的n-1个节点号(标号为0~n-2)中,第i个以后(包括第i个)有几个u。      

      这样对于第i个节点号,u=a[i],求与它相连的v的时候,只要遍历一下所有num[u][i]=0并且之前还没被用过的情况,选取其中最小的值,与当前的rest数组中最小的值比较,最小的那个即使v。      

       将n-1对(u,v)存入到另一个数组,最后建树即可。

    不知道怎么回事,一开始用puts(),getline(),结果都是Output Limit Exceeded,可能自己使用有些错误吧。
    后来看了网上别人用sstream类库读取数据的方法,这才AC。。。

    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    #include <string.h>
    #include <string>
    #include <vector>
    #include <sstream>
       
    using namespace std;
    const int maxn=55;
    int a[maxn];
    int num[maxn][maxn];  //num[u][i]表示在a[i]以后(包括a[i])有几个a[i]。
    int vis[maxn];  //vis[i]=1表示i在给出的数据中,=0即剩下的点
    int rest[maxn]; //存储给出的数据中未出现的点的编号
    int used[maxn]; //标记哪些点已经用过了
    vector<int>son[maxn];
    struct Node{
        int u,v;  //u是给出的数据中的节点,v是与它们相连的被删去的节点
    }node[maxn];
    
    void dfs(int u){
        printf("(");
        printf("%d",u);
        for(int i=0;i<son[u].size();i++){
            printf(" ");  //不打空格,也AC
            dfs(son[u][i]);
        }
        printf(")");
    }
    int main()
    {
        string buf;
        char ch,str[200];
        int idx,u,v,minv;
        while(getline(cin,buf)){
            for(int i=0;i<maxn;i++)
                son[i].clear();
            memset(vis,0,sizeof(vis));
            memset(num,0,sizeof(num));
            memset(used,0,sizeof(used));
    
            stringstream ss(buf);
            for(idx=0;ss>>a[idx];idx++);
            //预处理num[][]。
            for(int i=idx-1;i>=0;i--){
                vis[a[i]]=1;  //标记出现过的节点号
                num[a[i]][i]=num[a[i]][i+1]+1;
                for(int j=0;j<idx;j++){
                    if(a[j]!=a[i])
                        num[a[j]][i]=num[a[j]][i+1];
                }
            }
            int rlen=0,r=0; //rlen为rest数组的长度,r是指针,指向当前最小的值
            for(int i=1;i<=a[idx-1];i++){
                if(!vis[i]){
                    rest[rlen++]=i;
                }
            }
            sort(rest,rest+rlen);
            int k=0;
            for(int i=0;i<idx;i++){
                u=a[i];
                minv=60;
                //选取num[a[j]]=0和rest[r]中的最小值,即为与u相连的被删去的节点。
                //注意a[j]是未被使用过的,used[a[j]]=1表明a[j]在之前就被删去了,也就不可能在这次删去节点a[j]
                for(int j=0;j<idx;j++){
                    if(num[a[j]][i]==0 && a[j]<minv && !used[a[j]]){
                        minv=a[j];
                    }
                }
                if(r<rlen && rest[r]<minv){
                    minv=rest[r];
                    r++;
                }
                used[minv]=1;
                node[k].u=u;
                node[k].v=minv;
                k++;
            }
            //建树
            for(int i=0;i<k;i++){
                u=node[i].u;
                v=node[i].v;
                son[u].push_back(v);
            }
            //即如果读入的一行是空的,那么就只有1个节点1
            if(a[idx-1]==0)
                a[idx-1]=1;
            dfs(a[idx-1]);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    VM安装CentOs7虚拟机后无法上网之解决方法
    vue中touchEnd事件和touchStart、touchMove获取坐标不一样,IOS绑定touch事件失效
    【个推独家】让你一次性掌握Neo4j性能优化秘籍的三大狠招
    【深度干货】异构数据的SQL一站式解决方案
    个推基于Jenkins的自动打包构建实践
    个推CTO叶新江专访| 数据智能的未来,是不提大数据但其无所不在的时代
    应用系统间数据传输方式总结(附相关概念解释)
    JavaScript中“&&”和“||”操作符的意义,深入理解和使用场景
    静态布局、自适应布局、流式布局、响应式布局、弹性布局等的概念和区别
    前端跨域问题相关知识详解(原生js和jquery两种方法实现jsonp跨域)
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3355765.html
Copyright © 2020-2023  润新知