江苏就是江苏啊,题目质量高。
看到题的时候只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.
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen