如果发现广告等破坏行为,请尽量将条目恢复到较早的版本而不是把相应内容直接删除,谢谢合作。

URAL/1069

来自"NOCOW"

跳转到: 导航, 搜索

The Prufer code 时间限制: 2.0 s 内存限制: 1 000 KB


program cao;
const
  maxn=10000;
 
type
  node=record
    v,next:longint;
  end;
 
  Theap=object
    data:array[0..maxn] of longint;
    total:longint;
    procedure init;
    procedure insert(v:longint);
    procedure deletetop;
    function getmin:longint;
  end;
 
var
  heap:Theap;
  data,times,ans,head:array[0..maxn] of longint;
  t:array[0..maxn*2] of node;
  a,b,c,d,e,f,g,h,i,j,k,l,n,m,p,q,total,tmp:longint;
 
procedure swap(var a,b:longint);
begin
  tmp:=a;
  a:=b;
  b:=tmp;
end;
 
procedure qsort(left,right:longint);
var
  i,j,x:longint;
begin
  i:=left;
  j:=right;
  x:=ans[(i+j) shr 1];
  while i<j do
  begin
    while ans[i]<x do inc(i);
    while ans[j]>x do dec(j);
    if i<=j then
    begin
      swap(ans[i],ans[j]);
      inc(i);
      dec(j);
    end;
  end;
  if i<right then qsort(i,right);
  if j>left then qsort(left,j);
end;
 
procedure Theap.init;
begin
  total:=0;
end;
 
procedure Theap.insert(v:longint);
var
  i:longint;
begin
  inc(total);
  data[total]:=v;
  i:=total;
  while (i>1)and(data[i]<data[i shr 1]) do
  begin
    swap(data[i],data[i shr 1]);
    i:=i shr 1;
  end;
end;
 
procedure Theap.deletetop;
var
  i,j:longint;
begin
  data[1]:=data[total];
  dec(total);
  i:=1;
  while (i shl 1)<=total do
  begin
    j:=i shl 1;
    if (j+1<=total)and(data[j+1]<data[j]) then inc(j);
    if data[i]>data[j] then
    begin
      swap(data[i],data[j]);
      i:=j;
    end
    else break;
  end;
end;
 
function Theap.getmin:longint;
begin
  exit(data[1]);
end;
 
procedure init;
begin
  n:=0;
  while not(seekeof) do
  begin
    inc(n);
    read(data[n]);
  end;
end;
 
procedure main;
begin
  for i:=1 to n do
    inc(times[data[i]]);
  heap.init;
  for i:=1 to n+1 do
    if times[i]=0 then
      heap.insert(i);
  for i:=1 to n do
  begin
    k:=heap.getmin;
    inc(total);
    t[total].v:=k;
    t[total].next:=head[data[i]];
    head[data[i]]:=total;
    inc(total);
    t[total].v:=data[i];
    t[total].next:=head[k];
    head[k]:=total;
    dec(times[data[i]]);
    heap.deletetop;
    if times[data[i]]=0 then heap.insert(data[i]);
  end;
end;
 
procedure print;
begin
  for i:=1 to n+1 do
  begin
    k:=0;
    j:=head[i];
    while j<>0 do
    begin
      inc(k);
      ans[k]:=t[j].v;
      j:=t[j].next;
    end;
    qsort(1,k);
    write(i,':');
    for j:=1 to k do
      write(' ',ans[j]);
    writeln;
  end;
end;
 
begin
  init;
  main;
  print;
end.
//http://www.withflying.com/?p=131
//http://www.withflying.com

哥们,我觉得你好像写麻烦了……

我觉得应该先把给出的数据扫一遍,保存到一个数组里,得到n的值,顺便分别以节点的儿子数目和节点编号为第一第二关键字建一个最小堆。

然后从前往后再扫描一遍输入,对于输入中的每一个节点,将最小堆中最顶端的节点标记为前者的儿子并将前者的儿子数目减1,上浮。

居然要用到邻接表。注意,注意,我没有说过我的算法一定是正确的,求严格的证明/证伪过程。--Wecing 18:06 2010年5月8日 (CST)



同上 因为我用的就是这种方法 一次AC

证明其实也没什么好证明的 相当于是像拓扑排序一样从底端拓扑到上端 如果对一个有向无环图让我们每次都以最小点拓扑 答案即是这个 相当于给出拓扑输出让我们还原有向图。

弱弱的代码奉上:

program cyd;
  var
    p:array[1..7500]of boolean;
    d,e:array[1..7500]of integer;
    heap:array[1..7500]of integer;
    tou,next,f,po:array[1..7500]of integer;
    hp,i,j,k,l,m,n,a,c,tot:longint;
  procedure swap(var a,b:integer);
    var
      tmp:longint;
    begin
      tmp:=a;
      a:=b;
      b:=tmp;
    end;
  procedure qsort(l,r:longint);
    var
      tl,tr,mid,tmp:longint;
    begin
      tl:=l; tr:=r; mid:=d[(l+r)div 2];
      repeat
        while d[tl]>mid do inc(tl);
        while d[tr]<mid do dec(tr);
        if tl<=tr then
          begin
            swap(d[tl],d[tr]);
            inc(tl); dec(tr);
          end;
        until tl>tr;
      if l<tr then qsort(l,tr);
      if r>tl then qsort(tl,r);
    end;
  procedure add(a:longint);
    var
      x,y:longint;
    begin
      inc(hp);
      heap[hp]:=a;
      x:=hp;
      while x>1 do
        begin
          y:=x div 2;
          if heap[x]<heap[y] then swap(heap[x],heap[y]) else break;
          x:=y;
        end;
    end;
  procedure del;
    var
      x,y:longint;
    begin
      if hp=1 then begin dec(hp); exit; end;
      heap[1]:=heap[hp];
      dec(hp);
      x:=1;
      while x*2<=hp do
        begin
          y:=x*2;
          if (y+1<=hp)and(heap[y+1]<heap[y]) then inc(y);
          if heap[y]<heap[x] then swap(heap[y],heap[x]) else break;
          x:=y;
        end;
    end;
  begin
    while not eof do
      begin
        read(a);
        if a=0 then break;
        inc(n);
        d[n]:=a;
        inc(e[a]);
        p[a]:=true;
      end;
    inc(n);
    for i:=1 to n do
      if not p[i] then add(i);
    for i:=1 to n-1 do
      begin
        a:=heap[1];
        del;
        inc(tot);
        po[tot]:=a;
        next[tot]:=tou[d[i]];
        tou[d[i]]:=tot;
        f[a]:=d[i];
        dec(e[d[i]]);
        if e[d[i]]=0 then add(d[i]);
      end;
    for i:=1 to n do
      begin
        write(i,': ');
        j:=tou[i];
        k:=0;
        while j<>0 do
          begin
            inc(k);
            d[k]:=po[j];
            j:=next[j];
          end;
        if f[i]<>0 then begin inc(k); d[k]:=f[i]; end;
        qsort(1,k);
        for j:=k downto 2 do
          write(d[j],' ');
        writeln(d[1]);
      end;
  end.

stl表示毫无鸭梨

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <set>
using std::sort;
using std::set;
const int maxn=7510;
int n=1,t,tot=0,a[maxn],e[maxn]={0},out[maxn];
int h[maxn]={0},node[maxn<<1],next[maxn<<1];
set<int> x;
void add(int a,int b)
{
    node[++tot]=b;
    next[tot]=h[a];
    h[a]=tot;
}
int main()
{
    int i,j;
    while (scanf("%d",&a[n++]) != EOF);
    --n;
    for (i=1;i<n;++i)  ++e[a[i]];
    for (i=1;i<=n;++i)
        if (!e[i])
            x.insert(i);
    for (i=1;i<n;++i)
    {
        t=*x.begin();
        x.erase(t);
        add(t,a[i]);
        add(a[i],t);
        if (!(--e[a[i]]))  x.insert(a[i]);
    }
    for (i=1;i<=n;++i)
    {
        printf("%d:",i);
        for (tot=0,j=h[i];j;j=next[j])
            out[tot++]=node[j];
        sort(out,out+tot);
        for (j=0;j<tot;++j)  printf(" %d",out[j]);
        printf("\n");
    }
    return 0;
}
//by zzy
个人工具