zoukankan      html  css  js  c++  java
  • Bzoj 1016

    题目大意:求可能的最小生成树有多少棵、

    解:这个要用一些证明,这里只写自己的一些看完各神牛的blog后的想法总结,证明并不严谨。

    首先我们用kruskal求最小生成树的原理是,用权值为c的边把一些强连通分量连起来,然后c从小到大递增,用并查集判可行性。如果反证伪,则在最后一步时,存在比c小的边把强连通分量连起来了,但kruskal的特性不会让这种事情发生。所以可以证明,在第n步,对于 相同的图 来说,如果存在不同的最小生成树,对应的不同只是在第n步选择的边的可能,而设原最小生成树的第n步用的边的大小为c,那么一定有其他最小生成树的第n步,用的边也一定是c,而且使用的边的数量相同,而且连接的强连通分量的点集一定相同(因为不同则从第一步开始,每个强连通分量都是点自己,如果比第一次做的点要多,说明有n-1条树边中,有的边变小了[如原来用a条c边,现在用b条c边,而多出来的b-a在原来的生成树中是大于c的],所以违反了最小生成树的原理,同理可证少了),所以像构建最小生成树一样,从最小的边开始,在权值为c的边中,以2^p枚举可能,用乘法原理相乘即可。

    View Code
      1 //bzoj 1016 [JSOI2008] zuixiaoshengchengshujishu
      2 const
      3         maxm=1111;
      4         maxn=111;
      5         inf='1.txt';
      6         def=31011;
      7 type
      8         type_edge=record
      9           a, b: longint;
     10           cost: qword;
     11         end;
     12 var
     13         edge: array[0..maxm]of type_edge;
     14         f, f_2:array[0..maxn]of longint;
     15         n, m: longint;
     16         cnt, ans, key: qword;
     17 procedure qsort(b, e: longint);
     18 var
     19         i, j, x: longint;
     20         k: type_edge;
     21 begin
     22   i := b; j := e; x := edge[(i+j)>>1].cost;
     23   repeat
     24     while edge[i].cost<x do inc(i);
     25     while edge[j].cost>x do dec(j);
     26     if i<=j then begin
     27       k := edge[i]; edge[i] := edge[j]; edge[j] := k;
     28       inc(i); dec(j);
     29     end;
     30   until i>j;
     31   if j>b then qsort(b, j);
     32   if i<e then qsort(i, e);
     33 end;
     34 
     35 function getf(x: longint): longint;
     36 begin
     37   if f[x] = x then exit(x);
     38   f[x] := getf(f[x]);
     39   exit(f[x]);
     40 end;
     41 
     42 function getfex(x: longint): longint;
     43 begin
     44   if x=f_2[x] then exit(x);
     45   getfex := getfex(f_2[x]);
     46 end;
     47 
     48 procedure init;
     49 var
     50         i: longint;
     51 begin
     52   readln(n, m);
     53   for i := 1 to m do with edge[i] do readln(a, b, cost);
     54   for i := 1 to n do begin
     55     f[i] := i; f_2[i] := i;
     56   end;
     57   qsort(1, m);
     58   ans := 1; key := 0;
     59 end;
     60 
     61 procedure dfs(st, ed, num: longint);
     62 var
     63         a, b: longint;
     64 begin
     65   if num=0 then begin
     66     inc(cnt); exit;
     67   end;
     68   if st>ed then exit;
     69   a := getfex(edge[st].a); b := getfex(edge[st].b);
     70   if a<>b then begin
     71     f_2[a] := b;
     72     dfs(st+1, ed, num-1);
     73     f_2[a] := a;
     74   end;
     75   dfs(st+1, ed, num);
     76 end;
     77 
     78 function find(st, ed, num: longint): qword;
     79 begin
     80   cnt := 0;
     81   dfs(st, ed, num);
     82   if cnt=0 then find := 1
     83     else find := cnt;
     84 end;
     85 
     86 procedure main;
     87 var
     88         i, j, now, num, a, b: longint;
     89 begin
     90   now := 1; num := 0;
     91   for i := 1 to m do begin
     92     if (i<>1)and(edge[i].cost<>edge[i-1].cost) then begin
     93       ans := ans * find(now, i-1, num) mod def;
     94       f_2 := f;
     95       num := 0;
     96       now := i;
     97     end;
     98     a := getf(edge[i].a); b := getf(edge[i].b);
     99     if a<>b then begin
    100       inc(key); inc(num);
    101       f[a] := b;
    102     end;
    103     if key=n-1 then break;
    104   end;
    105   while (i<m)and(edge[i].cost=edge[i+1].cost) do inc(i);
    106   ans := ans * find(now, i, num) mod def;
    107 end;
    108 
    109 procedure print;
    110 begin
    111   if key=n-1 then writeln(ans)
    112     else writeln(0);
    113 end;
    114 
    115 begin
    116   assign(input,inf); reset(input);
    117   init;
    118   main;
    119   print;
    120 end.
  • 相关阅读:
    边工作边刷题:70天一遍leetcode: day 11-1
    边工作边刷题:70天一遍leetcode: day 11
    边工作边刷题:70天一遍leetcode: day 12-1
    边工作边刷题:70天一遍leetcode: day 12
    边工作边刷题:70天一遍leetcode: day 13-1
    边工作边刷题:70天一遍leetcode: day 13-2
    边工作边刷题:70天一遍leetcode: day 13
    边工作边刷题:70天一遍leetcode: day 14-1
    边工作边刷题:70天一遍leetcode: day 14
    边工作边刷题:70天一遍leetcode: day 15
  • 原文地址:https://www.cnblogs.com/wmzisfoolish/p/2469582.html
Copyright © 2011-2022 走看看