• bzoj2753


    第一问dfs不说

    第二问很容易让人想到最小树形图,但是我不会,而且时间复杂度也不允许

    还有什么不同的方法呢?

    首先想到的是prim的思想,设根节点已经确定,其他点未确定

    我们就不断从已确定的点延伸,找到到未确定点中高度最高的那个点的最短边距(如果有多个高度相同的点,肯定选边距最短的)

    将边距加入ans,并将这个点标为确定,重复上述,知道所有点都确定即可。

    这样的算法没有问题,但是复杂度好像仍然不能AC

    我们想,既然我们能用类似prim的思想,为什么不用Kruska呢?

    Kruskal的问题在于,这个算法是不涉及到边的方向,用这个不能选出符合条件的解

    考虑之前我们用类似prim的思想解题的时候,是以点的高度为第一关键字,然后再以距离为第二关键字

    Kruskal对边排序的时候,我们是不是也可以考虑以点的高度为第一关键字,然后以距离为第二关键字排序呢?

    就是这样,我们以边的终点高度为第一关键字降序,长度为第二关键字升序排序

    然后按最小生成树的方法做就行了。

    结果竟然TLE了,仔细对照一下别人的程序发现一直以来我的并查集写的是有问题的

    我原来getfather是这么写的

    function getf(x:longint):longint;

      begin

        while fa[x]<>x do x:=fa[x];

        exit(x);

      end;

    而实际上多次调用这个函数,显然会进行很多冗余的运算

    而正确的写法应该是

    function getf(x:longint):longint;

      begin

        if fa[x]<>x then fa[x]:=getf(fa[x]); 

        exit(fa[x]);

      end;

    这应该才是并查集所谓反阿克曼函数的时间复杂度吧

    亡羊补牢,为时不晚;

      1 type node=record
      2        x,c,y,next:longint;
      3      end;
      4 
      5 var a:array[0..2000010] of node;
      6     fa,p,q,h:array[0..110010] of longint;
      7     v:array[0..110010] of boolean;
      8     len,x,y,z,n,m,i,j,k1,k2,t:longint;
      9     ans,e:int64;
     10 
     11 procedure swap(var a,b:node);
     12   var c:node;
     13   begin
     14     c:=a;
     15     a:=b;
     16     b:=c;
     17   end;
     18 
     19 function getf(x:longint):longint;
     20   begin
     21     if fa[x]<>x then fa[x]:=getf(fa[x]); // 22     exit(fa[x]);
     23   end;
     24 
     25 procedure add(x,y,z:longint);
     26   begin
     27     inc(len);
     28     a[len].y:=y;
     29     a[len].c:=z;
     30     a[len].x:=x;
     31     a[len].next:=p[x];
     32     p[x]:=len;
     33   end;
     34 
     35 procedure bfs;
     36   var i,f,x,y:longint;
     37   begin
     38     t:=1;
     39     q[1]:=1;
     40     v[1]:=true;
     41     f:=1;
     42     while f<=t do
     43     begin
     44       x:=q[f];
     45       i:=p[x];
     46       while i<>-1 do
     47       begin
     48         y:=a[i].y;
     49         if not v[y] then
     50         begin
     51           v[y]:=true;
     52           inc(t);
     53           q[t]:=y;
     54         end;
     55         i:=a[i].next;
     56       end;
     57       inc(f);
     58     end;
     59   end;
     60 
     61 procedure sort(l,r:longint);
     62   var i,j,x,y,z:longint;
     63   begin
     64     i:=l;
     65     j:=r;
     66     x:=a[(l+r) shr 1].c;
     67     y:=a[(l+r) shr 1].y;
     68     repeat
     69       while (h[a[i].y]>h[y]) or (h[a[i].y]=h[y]) and (a[i].c<x) do inc(i);
     70       while (h[y]>h[a[j].y]) or (h[a[j].y]=h[y]) and (x<a[j].c) do dec(j);
     71       if not(i>j) then
     72       begin
     73         swap(a[i],a[j]);
     74         inc(i);
     75         j:=j-1;
     76       end;
     77     until i>j;
     78     if l<j then sort(l,j);
     79     if i<r then sort(i,r);
     80   end;
     81 
     82 
     83 begin
     84   fillchar(p,sizeof(p),255);
     85   readln(n,m);
     86   len:=0;
     87   for i:=1 to n do
     88     read(h[i]);
     89   for i:=1 to m do
     90   begin
     91     readln(x,y,z);
     92     if h[x]>h[y] then add(x,y,z)
     93     else begin
     94       add(y,x,z);
     95       if h[x]=h[y] then add(x,y,z);
     96     end;
     97   end;
     98   bfs;
     99   sort(1,len);
    100   for i:=1 to n do
    101     fa[i]:=i;
    102   i:=0;
    103   j:=0;
    104   for j:=1 to len do
    105   begin
    106     if not(v[a[j].x] and v[a[j].y]) then continue;  //首先必须是能访问到的点
    107     k1:=getf(a[j].x);
    108     k2:=getf(a[j].y);
    109     if k1<>k2 then
    110     begin
    111       fa[k2]:=k1;
    112       e:=a[j].c;
    113       ans:=ans+e;
    114       inc(i);
    115     end;
    116   end;
    117   writeln(t,' ',ans);
    118 end.
    View Code
  • 相关阅读:
    使用 OpCache 提升 PHP 性能
    在线视频开发博客教程
    修正ECMALL在PHP5.3以上版本中无法开启支付方式的BUG
    第二个小项目的讲解后感言
    mybatis进行分页,使用limit
    mybatis传递多个参数值(转)
    一个关于前端页面的小标签<tbody>
    json-lib的一些过滤操作
    关键字volidate和transient(转)
    Java中实现序列化的两种方式 Serializable 接口和 Externalizable接口
  • 原文地址:https://www.cnblogs.com/phile/p/4473200.html
Copyright © 2020-2023  润新知