江苏就是江苏啊,题目质量高。

看到题的时候只YY出了第一个性质:MST中边权相同的的边的个数是一定的。(证略,可以用反证法)

后来上网找题解,发现还有第二个性质:MST如果用Kruskal来做,做完长度为x的所有边以后,此时图的连通性是确定的。(这也是很明显的)

于是嘛。。。先算出每个长度的边的cnt,然后每次暴力枚举哪些边在MST中。

判断方式就是看新加的边有没有使得原来不联通的块联通,然后就做完了。

但是要注意的是,暴力枚举的时候并查集不能路径压缩,因为还要还原。

 

  1 /**************************************************************
  2     Problem: 1016
  3     User: rausen
  4     Language: Pascal
  5     Result: Accepted
  6     Time:8 ms
  7     Memory:344 kb
  8 ****************************************************************/
  9  
 10 {$inline on}
 11  
 12 const prime = 31011;
 13  
 14 var
 15   n, m, k, t : longint;
 16   i, x, y, z : longint;
 17   count, ans : longint;
 18   a, b, c, p, cnt, fa : array[0..5000] of longint;
 19   flag : boolean;
 20  
 21 procedure add_edge(x, y, z : longint); inline;
 22 begin
 23   inc(t);
 24   a[t] := x;
 25   b[t] := y;
 26   c[t] := z;
 27 end;
 28  
 29 procedure swap(x, y : longint); inline;
 30 var
 31   t : longint;
 32  
 33 begin
 34   t := a[x]; a[x] := a[y]; a[y] := t;
 35   t := b[x]; b[x] := b[y]; b[y] := t;
 36   t := c[x]; c[x] := c[y]; c[y] := t;
 37 end;
 38  
 39 procedure qsort(l, r : longint);
 40 var
 41   i, j, x : longint;
 42  
 43 begin
 44   i := l;
 45   j := r;
 46   x := c[(i + j) shr 1];
 47   repeat
 48     while c[i] < x do inc(i);
 49     while c[j] > x do dec(j);
 50     if i <= j then begin
 51       swap(i, j);
 52       inc(i);
 53       dec(j);
 54     end;
 55   until i > j;
 56   if i < r then qsort(i, r);
 57   if l < j then qsort(l, j);
 58 end;
 59  
 60 function find_fa(x : longint) : longint;
 61 var
 62   f : longint;
 63  
 64 begin
 65   f := fa[x];
 66   if f = x then exit(f);
 67   f := find_fa(f);
 68   fa[x] := f;
 69   exit(f);
 70 end;
 71  
 72 procedure make_mst;
 73 var
 74   i, j, f1, f2 : longint;
 75  
 76 begin
 77   for i := 1 to n do
 78     fa[i] := i;
 79   j := 0;
 80   fillchar(cnt, sizeof(cnt), 0);
 81   for i := 1 to t do begin
 82     if c[i] <> c[i - 1] then inc(j);
 83     f1 := find_fa(a[i]);
 84     f2 := find_fa(b[i]);
 85     if f1 <> f2 then begin
 86       inc(cnt[j]);
 87       fa[f1] := f2;
 88     end;
 89   end;
 90 end;
 91  
 92 function find_f(x : longint) : longint; inline;
 93 begin
 94   while fa[x] <> x do
 95     x := fa[x];
 96   exit(x);
 97 end;
 98  
 99 procedure sub(l, r, num : longint);
100 var
101   f1, f2 : longint;
102  
103 begin
104   if num = 0 then begin
105     inc(count);
106     if count > prime then
107       count := count - prime;
108     exit;
109   end;
110   if l > r then exit;
111   if r - l + 1 > num then sub(l + 1, r, num);
112   f1 := find_f(a[l]);
113   f2 := find_f(b[l]);
114   if f1 <> f2 then begin
115     fa[f1] := f2;
116     sub(l + 1, r, num - 1);
117     fa[f1] := f1;
118   end;
119 end;
120  
121 procedure make_ans;
122 var
123   i, j, f1, f2 : longint;
124  
125 begin
126   for i := 1 to n do
127     fa[i] := i;
128   ans := 1;
129   for i := 1 to k do begin
130     count := 0;
131     sub(p[i], p[i + 1] - 1, cnt[i]);
132     ans := (ans * count) mod prime;
133     for j := p[i] to p[i + 1] - 1 do begin
134       f1 := find_fa(a[j]);
135       f2 := find_fa(b[j]);
136       if f1 <> f2 then fa[f1] := f2;
137     end;
138   end;
139 end;
140  
141 begin
142   readln(n, m);
143   for i := 1 to m do begin
144     read(x, y, z);
145     add_edge(x, y, z);
146   end;
147   qsort(1, t);
148   p[1] := 1;
149   k := 1;
150   for i := 2 to t do
151     if c[i] <> c[i - 1] then begin
152       inc(k);
153       p[k] := i;
154     end;
155   p[k + 1] := t + 1;
156   make_mst;
157   make_ans;
158   flag := true;
159   for i := 1 to n do
160     if fa[i] = i then
161       if flag then flag := false
162       else begin
163         writeln(0);
164         exit;
165       end;
166   writeln(ans);
167 end.
View Code

 

posted on 2014-09-30 08:09  Xs酱~  阅读(243)  评论(0编辑  收藏  举报