题意:在树中,每次删去节点值最小的叶子结点。
每删去一个点,就给出与这相连的点的值,直到最后只剩下一个根结点,给这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; }