• 【BZOJ4474】isomorphism(树的同构,哈希)


    题意:一个无向树的度数为 2的结点称为假结点,其它结点称为真结点。一个无向树的简化树
    其结点由原树的全体真结点组成,两个真结点之间有边当且仅当它们在原树中有边,或者在
    原树中有一条联结这两个结点的路,其中间节点全是假结点。两个无向树各自的简化树如果
    同构,即存在结点之间的一一对应,使得在一个树中的任意两个结点之间有边当且仅当它们
    的对应结点在另一个树中有边,则称原来的两个无向树实质同构。给定若干个无向树,将相
    互实质同构的无向树只保留一个其余删除。统计剩下的相互不实质同构的无向树个数,并将
    它们的简化树结点个数从小到大输出。

    cas<=20 n<=10000

    思路:把很久以前在另一个地方写的题解搬过来

    定义题。做法请看题目。

    删除假节点并连边:先按输入构图并统计每个点的度数 找一个度不为2的点做一遍dfs

    if d[v]=2 f[find(u)]=f[find(v)]

    做完之后重连所有f[x[i]]<>f[y[i]]的边

    同构:

    哈希,将点上的哈希初值都=1,对于点u,取与u相连的点权V并排序,随意哈希作为新的哈希值。迭代10000000000000000000000000000000次。最后只需判断哈希值是否相等。

      1 const mo=1000000007;
      2 var head,vet,next,d,b,x,y,e1,q,f:array[0..20000]of longint;
      3     hash,s,c,h:array[1..20000]of int64;
      4     cas,v1,e,v,i,tot,len,n,j,k,ans:longint;
      5     tmp:int64;
      6     p:boolean;
      7   
      8 procedure qsort(l,r:longint);
      9 var i,j:longint;
     10     t,mid:int64;
     11 begin
     12  i:=l; j:=r; mid:=q[(l+r)>>1];
     13  repeat
     14   while mid>q[i] do inc(i);
     15   while mid<q[j] do dec(j);
     16   if i<=j then
     17   begin
     18    t:=q[i]; q[i]:=q[j]; q[j]:=t;
     19    inc(i); dec(j);
     20   end;
     21  until i>j;
     22  if l<j then qsort(l,j);
     23  if i<r then qsort(i,r);
     24 end;
     25   
     26 function find(k:longint):longint;
     27 begin
     28  if f[k]<>k then f[k]:=find(f[k]);
     29  find:=f[k];
     30 end;
     31   
     32 procedure add(a,b:longint);
     33 begin
     34  inc(tot);
     35  next[tot]:=head[a];
     36  vet[tot]:=b;
     37  head[a]:=tot;
     38 end;
     39   
     40 procedure dfs(u,fa:longint);
     41 var e,v:longint;
     42 begin
     43  e:=head[u];
     44  while e<>0 do
     45  begin
     46   v:=vet[e];
     47   if v<>fa then
     48   begin
     49    if d[v]=2 then f[find(v)]:=f[find(u)];
     50    dfs(v,u);
     51   end;
     52   e:=next[e];
     53  end;
     54 end;
     55   
     56 begin
     57    
     58  readln(cas);
     59   
     60  for v1:=1 to cas do
     61  begin
     62   read(n);
     63   fillchar(head,sizeof(head),0);
     64   fillchar(b,sizeof(b),0);
     65   fillchar(d,sizeof(d),0);
     66   for i:=1 to n do hash[i]:=1;
     67   for i:=1 to n do f[i]:=i;
     68   tot:=0;
     69   for i:=1 to n-1 do
     70   begin
     71    read(x[i],y[i]);
     72    inc(d[x[i]]); inc(d[y[i]]);
     73    add(x[i],y[i]);
     74    add(y[i],x[i]);
     75   end;
     76   for i:=1 to n do
     77    if d[i]<>2 then
     78    begin
     79     dfs(i,-1);
     80     break;
     81    end;
     82   tot:=0;
     83   fillchar(head,sizeof(head),0);
     84   
     85   
     86   for i:=1 to n-1 do
     87    if f[x[i]]<>f[y[i]] then
     88    begin
     89     b[f[x[i]]]:=1; b[f[y[i]]]:=1;
     90     add(f[x[i]],f[y[i]]);
     91     add(f[y[i]],f[x[i]]);
     92    end;
     93   for i:=1 to n do
     94    if d[i]<>2 then inc(e1[v1]);
     95   for i:=1 to 2 do
     96   begin
     97    for j:=1 to n do h[j]:=hash[j];
     98    for j:=1 to n do
     99     if b[j]=1 then
    100     begin
    101      e:=head[j];
    102      len:=0;
    103      while e<>0 do
    104      begin
    105       v:=vet[e];
    106       inc(len); q[len]:=h[v];
    107       e:=next[e];
    108      end;
    109      if len>0 then qsort(1,len);
    110      tmp:=0;
    111      for k:=1 to len do tmp:=(tmp*10003+q[k]) mod mo;
    112      hash[j]:=tmp;
    113   
    114     end;
    115   end;
    116   len:=0;
    117   for i:=1 to n do
    118    if b[i]=1 then begin inc(len); q[len]:=hash[i]; end;
    119   if len>0 then qsort(1,len);
    120   tmp:=0;
    121   for i:=1 to len do tmp:=(tmp*10003+q[i]) mod mo;
    122   
    123   s[v1]:=tmp;
    124  end;
    125  for i:=1 to cas do
    126  begin
    127   p:=true;
    128   for j:=1 to i-1 do
    129    if s[i]=s[j] then
    130    begin
    131     p:=false; break;
    132    end;
    133   if p then begin inc(ans); c[ans]:=e1[i]; end;
    134  end;
    135  for i:=1 to ans do q[i]:=c[i];
    136  qsort(1,ans);
    137  writeln(ans);
    138  for i:=1 to ans-1 do write(q[i],' ');
    139  write(q[ans]);
    140   
    141 end.
  • 相关阅读:
    WPF数据绑定机制是如何实现
    C#自定义特性的使用
    MVVMLight学习笔记(一)---MVVMLight概述
    C# Autofac学习笔记
    EFCodeFirst快速搭建入门
    SQL having与where用法区别
    EventWaitHandle 类
    C# EF 使用 (CodeFirst模式)
    wmi 远程启动程序
    Centos 7 的一些 基础知识
  • 原文地址:https://www.cnblogs.com/myx12345/p/7152544.html
Copyright © 2020-2023  润新知