├── .gitignore ├── Cargo.toml ├── cpp ├── solve.h └── solve.cpp ├── LICENSE ├── src ├── bin │ ├── track1.rs │ └── track2.rs └── lib.rs ├── README.md ├── result1.tsv ├── result3.tsv └── result2.tsv /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target 3 | **/*.rs.bk 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "steiner" 3 | version = "0.1.0" 4 | authors = ["Yoichi Iwata ", "Takuto Shigemura"] 5 | build = "build.rs" 6 | 7 | [dependencies] 8 | 9 | [build-dependencies] 10 | cc = "1.0" 11 | 12 | [profile.release] 13 | codegen-units = 1 14 | -------------------------------------------------------------------------------- /cpp/solve.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | extern "C" { 3 | /* 4 | input: 5 | 6 | N: 7 | M: 8 | edges: x1 y1 c1 x2 y2 c2 ... xM yM cM 9 | T: num of terminals 10 | terminals: t1 t2 .. tT 11 | 12 | V: the number of vertices in tree-decomposition 13 | td: 14 | k1 v1 v2 .. v_{k1} 15 | k2 v1 v2 .. v_{k2} 16 | : 17 | kV v1 v2 .. v_{kV} 18 | 19 | tedges: 20 | x1 y1 21 | x2 y2 22 | : 23 | x_{K-1} y_{K-1} 24 | 25 | output: 26 | return K: the number of edges used 27 | ans: 28 | x1 y1 x2 y2 .. x_K y_K 29 | */ 30 | int solve(int N, int M, int* edges, int T, int* terminals, int V, int* td, int* tedges, int* ans); 31 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Yoichi Iwata 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/bin/track1.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | 3 | extern crate steiner; 4 | use steiner::*; 5 | 6 | use std::io::BufRead; 7 | 8 | // Each edge must have positive weight (weight zero is not allowed). 9 | fn read_input() -> (G, Vec) { 10 | let mut es: Vec<(usize, usize, W)> = vec![]; 11 | let mut ts: Vec = vec![]; 12 | let stdin = std::io::stdin(); 13 | for line in stdin.lock().lines() { 14 | let line = line.unwrap(); 15 | let ss: Vec<&str> = line.split_whitespace().collect(); 16 | if ss.len() > 0 { 17 | if ss[0] == "E" { 18 | es.push((ss[1].parse().unwrap(), ss[2].parse().unwrap(), ss[3].parse().unwrap())); 19 | } else if ss[0] == "T" { 20 | ts.push(ss[1].parse::().unwrap() - 1); 21 | } else if ss[0] == "SECTION" && ss[1] == "Tree" { 22 | break; 23 | } 24 | } 25 | } 26 | let mut n = 0; 27 | for &(u, v, _) in &es { 28 | n.setmax(u); 29 | n.setmax(v); 30 | } 31 | let mut g = vec![vec![]; n]; 32 | for &(u, v, w) in &es { 33 | g[u - 1].push((v - 1, w)); 34 | g[v - 1].push((u - 1, w)); 35 | } 36 | (g, ts) 37 | } 38 | 39 | fn main() { 40 | let stime = std::time::SystemTime::now(); 41 | let (g, ts) = read_input(); 42 | eprintln!("n = {}\nm = {}\nT = {}", g.len(), g.iter().map(|a| a.len()).sum::() / 2, ts.len()); 43 | let reduced = Reduction::reduce(&g, &ts, &None); 44 | eprintln!("n' = {}\nm' = {}\nT' = {}", reduced.g.len(), reduced.g.iter().map(|a| a.len()).sum::() / 2, reduced.ts.len()); 45 | let time = std::time::SystemTime::now().duration_since(stime).unwrap(); 46 | eprintln!("reduce = {:.3}", time.as_secs() as f64 + time.subsec_nanos() as f64 * 1e-9); 47 | let (w, es) = pruned::solve(&reduced.g, &reduced.ts); 48 | let (w, es) = reduced.restore(w, es); 49 | let time = std::time::SystemTime::now().duration_since(stime).unwrap(); 50 | eprintln!("value = {}", w); 51 | eprintln!("time = {:.3}", time.as_secs() as f64 + time.subsec_nanos() as f64 * 1e-9); 52 | if !validate(&g, &ts, w, &es) { 53 | eprintln!("value = WA"); 54 | eprintln!("time = WA"); 55 | panic!("orz"); 56 | } 57 | println!("VALUE {}", w); 58 | for (u, v) in es { 59 | println!("{} {}", u + 1, v + 1); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Steiner tree solver 2 | This is an exact solver for Steiner tree problem which was submitted to the Parameterized Algorithms and Computational Experiments Challenge 2018 (https://pacechallenge.wordpress.com/pace-2018/). 3 | Preliminary results against the public data set: [result1.tsv](result1.tsv), [result2.tsv](result2.tsv), [result3.tsv](result3.tsv) 4 | 5 | ## Required 6 | - Rust (https://www.rust-lang.org/) 7 | - g++ 8 | 9 | ## How to build 10 | The following command creates two binaries `track1` and `track2` at `./target/release/`. 11 | ~~~ 12 | $ cargo build --release 13 | ~~~ 14 | `track1` is for inputs with a small number of terminals and `track2` is for inputs with a small tree-width. 15 | 16 | ## Algorithm 17 | 18 | ### Track1 (small number of terminals) 19 | Based on the standard O(3^k n + 2^k m log n)-time FPT algorithm by Erickson, Monma, and Veinott [1], where k is the number of terminals, we implemented the following separator-based pruned DP algorithm. 20 | Let A be the set of terminals. For a vertex v and a set I \subseteq A, we compute the minimum weight d[v][I] of a Steiner tree for I+v as follows. 21 | - Sending step: Pick the smallest unprocessed set I and update d[v][I] for every v by the Dijkstra's algorithm. 22 | - Splitting step: For every processed set J with I \cap J = \emptyset and for every v, update d[v][I \cup J] \gets min(d[v][I \cup J], d[v][I] + d[v][J]). 23 | 24 | Instead of computing d[v][I] for every (v, I) by the above dynamic programming, we skip the computation of d[v][I] which cannot be a part of any optimal solutions by using the following key lemma. 25 | 26 | *Let a be the maximum value such that in A-I is connected in the graph G[{v | d[v][I] >= a}]. Then any Steiner tree for A-I must contain some vertex v with d[v][I] <= a. Therefore (v, I) with d[v][I] > a cannot be a part of any optimal solutions.* 27 | 28 | After the sending step, we safely delete every (v, I) with d[v][I] > a by the above lemma. We then apply the splitting step only for the remaining pairs. This significantly reduces the number of pairs we need to consider. We also use several other pruning and speeding-up techniques. We plan to publish the detail later in a paper. 29 | 30 | #### References 31 | 1. Erickson, R.E., Monma, C.L., Veinott Jr., A.F.: Send-and-split method for minimum-concave-cost network flows. Math. Oper. Res. 12(4), 634–664 (1987) 32 | 33 | 34 | ### Track2 (small tree-width) 35 | We implemented the standard O^*(tw^tw)-time dynamic programming algorithm on a tree-decomposition. This solves all the public instances of tw <= 8 and several instances of tw <= 10. 36 | The track1 solver also works very well for inputs with small tree-width because it can prune many pairs thanks to the existence of small separators. 37 | So in our track2 solver, we use the tree-decomposition DP algorithm only when tw <= 8 or (tw <= 10 and #terminals >= 300), and for the other cases, we use the track1 solver. 38 | 39 | ### Track3 (heuristic) 40 | We just submitted the track1 solver. 41 | 42 | 43 | ## Authors 44 | - Yoichi Iwata 45 | - Takuto Shigemura 46 | -------------------------------------------------------------------------------- /result1.tsv: -------------------------------------------------------------------------------- 1 | Original Reduced 2 | Input n m T n' m' T' Time 3 | instance001 53 80 4 2 1 1 0.002 4 | instance003 2500 5000 5 1834 4285 5 0.165 5 | instance005 2500 62500 5 2500 19971 5 4.526 6 | instance007 157 266 6 10 13 4 0.003 7 | instance009 57 84 8 15 20 6 0.002 8 | instance011 64 288 8 64 288 8 0.011 9 | instance013 640 960 9 319 635 9 0.023 10 | instance015 640 960 9 304 612 9 0.022 11 | instance017 640 960 9 324 642 9 0.041 12 | instance019 640 4135 9 640 4135 9 0.136 13 | instance021 640 4135 9 640 4135 9 0.124 14 | instance023 640 204480 9 640 204467 9 1.627 15 | instance025 640 204480 9 640 204460 9 2.385 16 | instance027 90 135 10 7 9 4 0.003 17 | instance029 179 293 10 0 0 0 0.003 18 | instance031 298 503 10 0 0 0 0.008 19 | instance033 331 560 10 0 0 0 0.006 20 | instance035 609 932 10 26 37 7 0.009 21 | instance037 777 1239 10 0 0 0 0.02 22 | instance039 875 1522 10 7 9 3 0.025 23 | instance041 898 1562 10 0 0 0 0.018 24 | instance043 918 1684 10 10 14 5 0.016 25 | instance045 1290 2270 10 5 6 3 0.037 26 | instance047 2500 5000 10 1878 4333 10 0.564 27 | instance049 3221 5938 10 494 883 10 1.39 28 | instance051 2500 12500 10 2481 10029 10 0.913 29 | instance053 128 227 11 84 150 9 0.01 30 | instance055 191 302 11 16 24 6 0.006 31 | instance057 237 390 11 11 16 5 0.005 32 | instance059 278 478 11 0 0 0 0.006 33 | instance061 353 608 11 2 1 1 0.007 34 | instance063 572 963 11 71 117 8 0.026 35 | instance065 720 1269 11 24 36 7 0.02 36 | instance067 3675 6709 11 919 1579 11 0.323 37 | instance069 64 192 12 64 192 12 0.228 38 | instance071 233 386 12 0 0 0 0.004 39 | instance073 386 653 12 0 0 0 0.008 40 | instance075 818 1462 12 265 453 11 0.071 41 | instance077 1981 3633 12 434 753 11 0.22 42 | instance079 4045 7094 12 207 343 11 0.25 43 | instance081 110 188 13 42 66 11 0.009 44 | instance083 346 583 13 42 65 9 0.016 45 | instance085 125 750 13 125 516 13 0.158 46 | instance087 125 750 13 125 750 13 1.546 47 | instance089 933 1632 13 7 9 4 0.033 48 | instance091 1359 2458 13 18 27 6 0.04 49 | instance093 165 274 14 0 0 0 0.003 50 | instance095 418 723 14 31 47 7 0.007 51 | instance097 1196 2084 14 87 142 8 0.026 52 | instance099 193 369 15 125 236 15 0.035 53 | instance101 311 579 16 201 367 15 0.073 54 | instance103 402 690 16 0 0 0 0.012 55 | instance105 712 1217 16 204 350 15 0.03 56 | instance107 837 1438 16 193 330 13 0.035 57 | instance109 1051 1791 16 261 447 16 0.047 58 | instance111 1848 3286 16 19 28 5 0.058 59 | instance113 6405 10454 16 2206 3776 10 0.63 60 | instance115 122 194 17 0 0 0 0.002 61 | instance117 220 374 17 0 0 0 0.004 62 | instance119 310 514 17 0 0 0 0.008 63 | instance121 343 559 17 44 69 10 0.009 64 | instance123 2039 3548 17 129 219 16 0.06 65 | instance125 211 380 18 158 281 18 0.03 66 | instance127 1709 2963 18 87 137 13 0.063 67 | instance129 3738 7013 18 344 622 13 1.131 68 | instance131 189 353 19 165 311 18 0.022 69 | instance133 321 540 20 104 160 16 0.018 70 | instance135 3683 6717 20 702 1192 17 0.414 71 | instance137 529 1032 21 363 702 21 0.602 72 | instance139 770 1383 21 71 116 16 0.026 73 | instance141 233 431 22 163 298 20 0.183 74 | instance143 828 1472 22 271 454 18 0.056 75 | instance145 132 230 23 113 196 23 0.005 76 | instance147 3983 7108 23 96 149 20 0.12 77 | instance149 493 963 24 387 751 24 0.237 78 | instance151 8007 14743 24 2740 4832 23 3.147 79 | instance153 246 468 25 214 402 25 0.056 80 | instance155 58 1653 25 37 122 11 0.005 81 | instance157 2213 4135 25 79 130 13 0.093 82 | instance159 3636 6789 25 106 178 15 0.191 83 | instance161 640 40896 25 640 40887 25 84 | instance163 640 40896 25 640 40876 25 85 | instance165 640 40896 25 640 40872 25 86 | instance167 396 781 26 329 657 26 2.805 87 | instance169 243 497 27 201 413 27 1.601 88 | instance171 243 1215 27 241 1066 25 89 | instance173 243 1215 27 243 1215 27 90 | instance175 307 559 28 246 445 28 0.107 91 | instance177 245 436 29 171 299 25 0.038 92 | instance179 1724 2975 29 217 369 26 0.168 93 | instance181 8013 14749 30 4005 7171 29 5.285 94 | instance183 1199 2078 31 122 193 22 0.047 95 | instance185 437 838 33 390 751 33 0.231 96 | instance187 1244 2474 34 1147 2292 33 2.901 97 | instance189 8017 14753 36 2851 5068 36 3.733 98 | instance191 2132 3702 37 413 728 29 0.321 99 | instance193 603 1207 38 517 1041 38 0.675 100 | instance195 550 5013 50 550 5013 50 101 | instance197 10393 18043 104 3635 6528 88 33.45 102 | instance199 6163 10490 130 3040 5376 109 9.278 103 | Score 94|83.143 104 | -------------------------------------------------------------------------------- /result3.tsv: -------------------------------------------------------------------------------- 1 | Original Reduced 2 | Input n m T n' m' T' Time 3 | instance001 6405 10454 16 2206 3776 10 0.789 4 | instance003 8007 14743 24 2740 4832 23 3.189 5 | instance005 8013 14749 30 4005 7171 29 5.575 6 | instance007 38282 71521 34 17544 31744 34 67.834 7 | instance009 3803 6213 38 895 1356 30 0.868 8 | instance011 19100 35653 40 8239 14818 38 31.764 9 | instance013 550 5013 50 550 5013 50 10 | instance015 1000 13500 50 1000 13500 50 11 | instance017 3716 6750 52 1896 3312 49 4.558 12 | instance019 38307 71546 58 16764 30221 57 327.955 13 | instance021 1331 19965 61 1331 11730 61 14 | instance023 1331 19965 61 1331 19965 61 15 | instance025 512 2304 64 507 2260 59 16 | instance027 1822 3610 64 1726 3456 60 11.071 17 | instance029 987 1923 67 765 1541 42 4.746 18 | instance031 1728 28512 74 1728 16302 74 19 | instance033 1728 28512 74 1728 28512 74 20 | instance035 1761 3370 76 1493 2926 68 18.268 21 | instance037 2346 4656 78 2024 4062 74 25.974 22 | instance039 320 640 80 253 558 73 23 | instance041 320 1845 80 320 1831 80 24 | instance043 1491 2831 80 1360 2610 76 25 | instance045 320 10208 80 320 9815 80 26 | instance047 320 51040 80 320 48333 80 27 | instance049 3168 6220 83 2935 5874 80 28 | instance051 528 1017 85 521 1005 85 378.21 29 | instance053 743 1409 88 587 1112 75 1.082 30 | instance055 1343 2594 91 1202 2360 79 838.06 31 | instance057 1976 3836 94 1673 3341 81 11.553 32 | instance059 2518 4985 96 2337 4686 89 292.674 33 | instance061 2265 4545 98 2059 4186 83 138.718 34 | instance063 9469 22743 100 9441 21672 97 534.197 35 | instance065 10393 18043 104 3635 6528 88 32.059 36 | instance067 3224 5285 126 825 1220 101 2.126 37 | instance069 1024 5120 135 1024 5120 135 38 | instance071 640 1280 160 506 1130 152 39 | instance073 640 4135 160 640 4083 160 40 | instance075 640 40896 160 640 38941 160 41 | instance077 640 204480 160 640 192611 160 42 | instance079 38418 71657 172 24621 44818 169 43 | instance081 44624 56205 190 8707 13276 187 44 | instance083 2200 7997 200 1819 7330 200 45 | instance085 1200 10002 200 1199 10000 200 46 | instance087 7527 18170 200 7497 17186 191 47 | instance089 33901 62816 204 14682 27459 197 48 | instance091 2187 15308 222 2187 15308 222 49 | instance093 2048 11263 244 2048 11263 244 50 | instance095 512 2304 256 512 2304 256 51 | instance097 3300 18073 300 3140 17795 300 52 | instance099 8755 14449 347 4481 6701 318 429.874 53 | instance101 9287 14975 363 3957 5894 312 54 | instance103 50002 65203 386 10548 16260 380 55 | instance105 783 2262 406 783 2262 406 56 | instance107 14685 23466 421 7924 11970 390 755.375 57 | instance109 12715 20632 475 4879 7301 410 58.764 58 | instance111 12355 19962 503 4800 7165 411 59 | instance113 1024 5120 512 1024 5120 512 60 | instance115 9574 16208 543 4103 6044 479 61 | instance117 79244 101189 550 15616 24129 541 62 | instance119 1081 3174 552 1081 3174 552 63 | instance121 5556 8552 570 1072 1536 292 64 | instance123 21808 34921 594 8306 12459 525 65 | instance125 20547 33230 627 11556 17471 583 66 | instance127 13316 22033 653 5318 7876 560 67 | instance129 15122 24371 737 7722 11578 628 68 | instance131 13294 21948 835 6347 9352 720 69 | instance133 15714 25567 871 7183 10615 749 70 | instance135 25081 40739 888 12407 18531 789 71 | instance137 97928 128632 902 20299 31518 888 72 | instance139 29905 47457 943 15077 22655 853 73 | instance141 30857 49591 990 17303 26171 858 74 | instance143 2676 3894 1000 1562 2507 476 75 | instance145 2865 4267 1000 1804 2905 539 76 | instance147 62174 87562 1015 14645 22594 980 77 | instance149 2048 11264 1024 2048 11264 1024 78 | instance151 42008 67572 1242 79 | instance153 33188 53680 1263 15448 23090 1140 80 | instance155 33118 55127 1553 81 | instance157 26840 43661 1645 11075 16264 1319 82 | instance159 30585 50454 1704 83 | instance161 72701 115430 1790 84 | instance163 117756 165153 1879 85 | instance165 88728 133625 2041 86 | instance167 4096 24576 2048 4096 24576 2048 87 | instance169 69988 111804 2162 88 | instance171 54351 88211 2182 89 | instance173 44934 73727 2319 90 | instance175 48833 79987 2493 91 | instance177 57551 95381 2973 92 | instance179 68464 108732 3001 93 | instance181 135543 201803 3033 94 | instance183 120866 187312 3224 95 | instance185 66048 110491 3343 96 | instance187 63158 107345 3458 97 | instance189 172687 255825 3902 98 | instance191 85085 138888 3954 99 | instance193 17127 27352 4461 13559 22238 3262 100 | instance195 89596 148583 4991 101 | instance197 235686 366093 6313 102 | instance199 18245 36038 17795 18245 36038 17795 103 | Score 24|3975.283 104 | -------------------------------------------------------------------------------- /result2.tsv: -------------------------------------------------------------------------------- 1 | Original Reduced 2 | Input n m T Tw+1 n' m' T' Tw'+1 Time 3 | instance001 74 146 25 6 51 89 19 5 0.011 4 | instance003 87 176 30 6 70 123 22 6 0.038 5 | instance005 201 253 100 6 75 117 27 6 0.031 6 | instance007 216 288 100 6 83 126 33 5 0.023 7 | instance009 229 312 100 6 113 176 41 6 0.068 8 | instance011 244 337 100 6 112 175 38 6 0.081 9 | instance013 1906 2083 1655 6 86 138 43 5 0.046 10 | instance015 114 228 33 7 80 143 23 7 0.061 11 | instance017 210 276 100 7 53 84 19 6 0.017 12 | instance019 231 319 100 7 113 178 42 7 0.205 13 | instance021 247 486 100 7 155 277 49 7 0.147 14 | instance023 990 1258 574 7 255 390 118 6 0.128 15 | instance025 8790 9815 7397 7 153 241 75 5 4.024 16 | instance027 15 35 8 8 15 35 8 8 0.247 17 | instance029 197 250 100 8 54 85 20 7 0.026 18 | instance031 269 399 99 8 131 213 43 8 0.577 19 | instance033 480 670 200 8 246 386 80 8 0.822 20 | instance035 543 727 250 8 219 342 79 8 0.65 21 | instance037 1172 1627 500 8 495 782 189 8 2.447 22 | instance039 1912 2223 1173 8 157 248 77 6 0.169 23 | instance041 2382 2674 1889 8 238 380 100 8 0.547 24 | instance043 246 468 25 9 214 402 25 9 17.312 25 | instance045 389 562 150 9 200 321 68 9 2.618 26 | instance047 585 799 250 9 229 350 92 7 0.127 27 | instance049 623 876 250 9 296 478 90 9 5.607 28 | instance051 1416 1978 657 9 608 968 222 9 8.526 29 | instance053 181 289 51 10 151 245 40 10 1.986 30 | instance055 233 431 22 10 163 298 20 10 0.246 31 | instance057 245 454 20 10 197 361 20 10 0.165 32 | instance059 560 870 195 10 358 586 109 10 62.178 33 | instance061 528 1017 85 10 521 1005 85 10 376.119 34 | instance063 1214 1700 500 10 606 955 210 9 1.771 35 | instance065 2856 3641 1748 10 875 1390 315 10 23.038 36 | instance067 200 370 20 11 18 27 7 4 0.011 37 | instance069 200 370 100 11 2 1 1 2 0.005 38 | instance071 339 522 100 11 236 386 64 11 0.667 39 | instance073 262 740 10 11 254 580 10 11 0.034 40 | instance075 557 1080 49 11 441 860 47 11 0.359 41 | instance077 2413 3412 1577 11 520 891 247 11 46.313 42 | instance079 36415 145635 16808 11 36415 145635 16808 11 43 | instance081 237 378 76 12 168 281 44 12 4.917 44 | instance083 311 632 32 12 261 535 32 12 7.897 45 | instance085 1274 1808 500 12 646 1027 200 12 219.958 46 | instance087 1337 1933 500 12 760 1206 243 11 47 | instance089 5829 7552 3038 12 1223 1941 488 11 8.706 48 | instance091 304 571 33 13 244 459 31 13 0.073 49 | instance093 1001 1419 400 13 496 786 168 13 122.579 50 | instance095 1335 1932 500 13 763 1210 249 13 51 | instance097 2629 3793 1000 13 1441 2313 464 13 52 | instance099 1294 1853 500 14 705 1114 234 11 473.52 53 | instance101 2778 4083 1000 14 1569 2515 491 14 54 | instance103 1055 1473 493 15 348 552 137 10 477.388 55 | instance105 1408 2056 500 15 781 1267 226 15 527.656 56 | instance107 160 240 24 16 74 141 19 16 0.421 57 | instance109 257 515 23 16 212 424 23 16 0.26 58 | instance111 2763 4038 1000 16 1580 2531 485 16 59 | instance113 80 160 16 17 62 135 16 17 4.17 60 | instance115 243 497 27 17 201 413 27 17 1.225 61 | instance117 398 788 44 17 302 600 41 17 0.231 62 | instance119 678 1030 318 17 272 468 108 10 0.21 63 | instance121 1005 1731 18 17 40 62 9 5 0.048 64 | instance123 2762 4047 1000 17 1582 2549 485 16 65 | instance125 160 240 24 18 72 139 17 17 2.565 66 | instance127 294 568 22 18 219 427 22 18 0.242 67 | instance129 323 592 31 18 227 409 30 15 0.103 68 | instance131 499 861 16 18 70 120 12 9 0.561 69 | instance133 766 1535 76 18 635 1273 74 18 2.168 70 | instance135 2532 3615 1000 18 1229 1968 388 18 71 | instance137 2676 3894 1000 18 1562 2507 476 18 72 | instance139 2984 4484 1000 18 1914 3086 562 18 73 | instance141 294 618 38 19 251 533 38 19 124.519 74 | instance143 388 815 45 19 355 753 45 19 75 | instance145 437 838 33 19 390 751 33 19 0.157 76 | instance147 564 1112 50 19 479 950 47 19 0.963 77 | instance149 615 1232 53 19 519 1042 53 19 11.118 78 | instance151 314 650 34 20 274 572 34 20 17.83 79 | instance153 670 1316 62 20 669 1315 62 20 0.69 80 | instance155 770 1383 21 20 71 116 16 7 0.114 81 | instance157 938 1869 75 20 779 1566 75 20 5.578 82 | instance159 2865 4267 1000 20 1804 2905 539 20 83 | instance161 2502 6244 100 24 2478 5700 92 24 11.516 84 | instance163 402 780 26 21 337 661 22 21 0.115 85 | instance165 422 808 25 21 327 623 25 21 0.095 86 | instance167 632 1087 10 21 101 167 9 10 0.015 87 | instance169 720 1269 11 21 24 36 7 4 0.014 88 | instance171 802 1553 39 21 502 950 38 19 0.383 89 | instance173 788 1938 50 21 772 1707 47 21 0.334 90 | instance175 2397 3715 783 21 1719 2797 497 21 91 | instance177 904 1806 59 22 681 1361 54 22 1.826 92 | instance179 752 1264 26 23 159 268 23 13 0.044 93 | instance181 757 1493 58 23 582 1171 58 22 24.615 94 | instance183 838 1763 60 23 834 1757 60 23 0.362 95 | instance185 2834 4207 1000 23 1706 2762 496 23 96 | instance187 529 1032 21 24 363 702 21 22 0.468 97 | instance189 467 896 30 25 388 743 30 24 0.165 98 | instance191 5096 8105 1379 26 3950 6469 977 26 99 | instance193 1848 3286 16 27 19 28 5 4 0.081 100 | instance195 1724 2975 29 28 217 369 26 17 0.13 101 | instance197 6128 15264 200 29 6082 14106 193 29 102 | instance199 1011 2010 37 37 968 1927 37 37 3.081 103 | Score 84|2616.558 104 | -------------------------------------------------------------------------------- /src/bin/track2.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | 3 | extern crate steiner; 4 | use std::collections::{BTreeSet, BTreeMap, BinaryHeap}; 5 | use steiner::*; 6 | 7 | use std::io::BufRead; 8 | 9 | // Each edge must have positive weight (weight zero is not allowed). 10 | fn read_input() -> (G, Vec) { 11 | let mut es: Vec<(usize, usize, W)> = vec![]; 12 | let mut ts: Vec = vec![]; 13 | let stdin = std::io::stdin(); 14 | for line in stdin.lock().lines() { 15 | let line = line.unwrap(); 16 | let ss: Vec<&str> = line.split_whitespace().collect(); 17 | if ss.len() > 0 { 18 | if ss[0] == "E" { 19 | es.push((ss[1].parse().unwrap(), ss[2].parse().unwrap(), ss[3].parse().unwrap())); 20 | } else if ss[0] == "T" { 21 | ts.push(ss[1].parse::().unwrap() - 1); 22 | } else if ss[0] == "SECTION" && ss[1] == "Tree" { 23 | break; 24 | } 25 | } 26 | } 27 | let mut n = 0; 28 | for &(u, v, _) in &es { 29 | n.setmax(u); 30 | n.setmax(v); 31 | } 32 | let mut g = vec![vec![]; n]; 33 | for &(u, v, w) in &es { 34 | g[u - 1].push((v - 1, w)); 35 | g[v - 1].push((u - 1, w)); 36 | } 37 | (g, ts) 38 | } 39 | 40 | fn read_tree_decomposition() -> Option { 41 | let stdin = std::io::stdin(); 42 | let mut lines = stdin.lock().lines(); 43 | let n; 44 | loop { 45 | if let Some(line) = lines.next() { 46 | let line = line.unwrap(); 47 | let ss: Vec<&str> = line.split_whitespace().collect(); 48 | if ss.len() > 0 && ss[0] == "s" && ss[1] == "td" { 49 | n = ss[2].parse().unwrap(); 50 | break; 51 | } 52 | } else { 53 | return None; 54 | } 55 | } 56 | let mut bs = vec![vec![]; n]; 57 | for _ in 0..n { 58 | let line = lines.next().unwrap().unwrap(); 59 | let ss: Vec<&str> = line.split_whitespace().collect(); 60 | assert_eq!(ss[0], "b"); 61 | let id = ss[1].parse::().unwrap() - 1; 62 | for j in 2..ss.len() { 63 | bs[id].push(ss[j].parse::().unwrap() - 1); 64 | } 65 | bs[id].sort(); 66 | } 67 | let mut es = vec![]; 68 | for _ in 0..n - 1 { 69 | let line = lines.next().unwrap().unwrap(); 70 | let ss: Vec<&str> = line.split_whitespace().collect(); 71 | es.push((ss[0].parse::().unwrap() - 1, ss[1].parse::().unwrap() - 1)); 72 | } 73 | Some((bs, es)) 74 | } 75 | 76 | pub fn compute_tree_decomposition(g: &G) -> TD { 77 | let n = g.len(); 78 | let mut g: Vec> = g.iter().map(|a| { 79 | a.iter().map(|&(u, _)| u).collect() 80 | }).collect(); 81 | let mut bags = vec![vec![]; n]; 82 | let mut depth = vec![!0; n]; 83 | let mut que = BinaryHeap::new(); 84 | for u in 0..n { 85 | que.push((!g[u].len(), u)); 86 | } 87 | let mut k = 0; 88 | while let Some((d, u)) = que.pop() { 89 | let d = !d; 90 | if depth[u] != !0 || g[u].len() != d { 91 | continue; 92 | } 93 | depth[u] = k; 94 | k += 1; 95 | g[u].insert(u); 96 | bags[u] = std::mem::replace(&mut g[u], BTreeSet::new()).into_iter().collect(); 97 | for &i in &bags[u] { 98 | if i == u { 99 | continue; 100 | } 101 | let di = g[i].len(); 102 | g[i].remove(&u); 103 | for &j in &bags[u] { 104 | if i != j && j != u { 105 | g[i].insert(j); 106 | } 107 | } 108 | if g[i].len() != di { 109 | que.push((!g[i].len(), i)); 110 | } 111 | } 112 | } 113 | let mut es = vec![]; 114 | for u in 0..n { 115 | if bags[u].len() > 1 { 116 | let mut p = !0; 117 | for &v in &bags[u] { 118 | if v != u && (p == !0 || depth[p] > depth[v]) { 119 | p = v; 120 | } 121 | } 122 | if p != !0 { 123 | es.push((u, p)); 124 | } 125 | } 126 | } 127 | (bags, es) 128 | } 129 | 130 | pub fn validate_td(g: &G, td: &TD) -> bool { 131 | let n = g.len(); 132 | let mut es = BTreeSet::new(); 133 | for u in 0..n { 134 | for &(v, _) in &g[u] { 135 | if u < v { 136 | es.insert((u, v)); 137 | } 138 | } 139 | } 140 | for bag in &td.0 { 141 | for i in 0..bag.len() { 142 | for j in i + 1..bag.len() { 143 | es.remove(&(bag[i], bag[j])); 144 | } 145 | } 146 | } 147 | if es.len() > 0 { 148 | let &(u, v) = es.iter().next().unwrap(); 149 | eprintln!("The tree-decomposition does not contain edge {}-{}.", u, v); 150 | return false; 151 | } 152 | let mut count_v = vec![0; n]; 153 | let mut count_e = vec![0; n]; 154 | for bag in &td.0 { 155 | for &v in bag { 156 | count_v[v] += 1; 157 | } 158 | } 159 | for &(i, j) in &td.1 { 160 | let mut p = 0; 161 | let mut q = 0; 162 | while p < td.0[i].len() && q < td.0[j].len() { 163 | match td.0[i][p].cmp(&td.0[j][q]) { 164 | std::cmp::Ordering::Equal => { 165 | count_e[td.0[i][p]] += 1; 166 | p += 1; 167 | q += 1; 168 | }, 169 | std::cmp::Ordering::Less => { 170 | p += 1; 171 | }, 172 | std::cmp::Ordering::Greater => { 173 | q += 1; 174 | }, 175 | } 176 | } 177 | } 178 | for v in 0..n { 179 | if count_v[v] > 0 && count_v[v] != count_e[v] + 1 { 180 | eprintln!("The bags containing {} are not connected.", v); 181 | return false; 182 | } 183 | } 184 | true 185 | } 186 | 187 | pub mod td { 188 | 189 | use ::*; 190 | 191 | mod cpp { 192 | extern { 193 | pub fn solve(N: i32, M: i32, edges: *const i32, T: i32, terminals: *const i32, V: i32, td: *const i32, tedges: *const i32, ans: *mut i32) -> i32; 194 | } 195 | } 196 | 197 | pub fn solve(g: &G, ts: &Vec, td: &TD) -> (W, Vec) { 198 | if ts.len() <= 1 { 199 | return (0, vec![]); 200 | } 201 | let N = g.len(); 202 | let mut edges = vec![]; 203 | for u in 0..N { 204 | for &(v, w) in &g[u] { 205 | if u < v { 206 | edges.push(u as i32); 207 | edges.push(v as i32); 208 | edges.push(w as i32); 209 | } 210 | } 211 | } 212 | let M = edges.len() / 3; 213 | let mut terminals = vec![]; 214 | for &t in ts { 215 | terminals.push(t as i32); 216 | } 217 | let V = td.0.len(); 218 | let mut bags = vec![]; 219 | for bag in &td.0 { 220 | bags.push(bag.len() as i32); 221 | for &v in bag { 222 | bags.push(v as i32); 223 | } 224 | } 225 | let mut tedges = vec![]; 226 | for &(u, v) in &td.1 { 227 | tedges.push(u as i32); 228 | tedges.push(v as i32); 229 | } 230 | let mut ans = vec![0; M * 2]; 231 | let K = unsafe { cpp::solve(N as i32, M as i32, edges.as_ptr(), ts.len() as i32, terminals.as_ptr(), V as i32, bags.as_ptr(), tedges.as_ptr(), ans.as_mut_ptr()) } as usize; 232 | let mut es = vec![]; 233 | for i in 0..K { 234 | es.push((ans[i * 2] as usize, ans[i * 2 + 1] as usize)); 235 | } 236 | let mut w = 0; 237 | let mut g2 = vec![BTreeMap::new(); N]; 238 | for u in 0..N { 239 | for &(v, w) in &g[u] { 240 | g2[u].entry(v).or_insert(INF).setmin(w); 241 | } 242 | } 243 | for &(u, v) in &es { 244 | if let Some(w1) = g2[u].get(&v) { 245 | w += w1; 246 | } else { 247 | panic!("illegal edge"); 248 | } 249 | } 250 | (w, es) 251 | } 252 | 253 | } 254 | 255 | fn main() { 256 | let stime = std::time::SystemTime::now(); 257 | let (g, ts) = read_input(); 258 | eprintln!("n = {}\nm = {}\nT = {}", g.len(), g.iter().map(|a| a.len()).sum::() / 2, ts.len()); 259 | let td = read_tree_decomposition(); 260 | if let Some(ref td) = td { 261 | let tw = td.0.iter().map(|b| b.len()).max().unwrap_or(0); 262 | eprintln!("tw = {}", tw); 263 | } 264 | let mut reduced = Reduction::reduce(&g, &ts, &td); 265 | eprintln!("n' = {}\nm' = {}\nT' = {}", reduced.g.len(), reduced.g.iter().map(|a| a.len()).sum::() / 2, reduced.ts.len()); 266 | let time = std::time::SystemTime::now().duration_since(stime).unwrap(); 267 | eprintln!("reduce = {:.3}", time.as_secs() as f64 + time.subsec_nanos() as f64 * 1e-9); 268 | let mut td = compute_tree_decomposition(&reduced.g); 269 | let time = std::time::SystemTime::now().duration_since(stime).unwrap(); 270 | eprintln!("decompose = {:.3}", time.as_secs() as f64 + time.subsec_nanos() as f64 * 1e-9); 271 | let mut tw = td.0.iter().map(|b| b.len()).max().unwrap_or(0); 272 | if let Some(ref td1) = reduced.td { 273 | let tw1 = td1.0.iter().map(|b| b.len()).max().unwrap_or(0); 274 | if tw >= tw1 { 275 | td = td1.clone(); 276 | tw = tw1; 277 | } 278 | } 279 | reduced.td = Some(td); 280 | eprintln!("tw' = {}", tw); 281 | if !validate_td(&reduced.g, reduced.td.as_ref().unwrap()) { 282 | panic!("orz"); 283 | } 284 | let (w, es) = if tw <= 9 || tw <= 11 && reduced.ts.len() >= 300 { 285 | td::solve(&reduced.g, &reduced.ts, reduced.td.as_ref().unwrap()) 286 | } else { 287 | pruned::solve(&reduced.g, &reduced.ts) 288 | }; 289 | let (w, es) = reduced.restore(w, es); 290 | let time = std::time::SystemTime::now().duration_since(stime).unwrap(); 291 | eprintln!("value = {}", w); 292 | eprintln!("time = {:.3}", time.as_secs() as f64 + time.subsec_nanos() as f64 * 1e-9); 293 | if !validate(&g, &ts, w, &es) { 294 | eprintln!("value = WA"); 295 | eprintln!("time = WA"); 296 | panic!("orz"); 297 | } 298 | println!("VALUE {}", w); 299 | for (u, v) in es { 300 | println!("{} {}", u + 1, v + 1); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /cpp/solve.cpp: -------------------------------------------------------------------------------- 1 | //#define _GLIBCXX_DEBUG 2 | #include "solve.h" 3 | 4 | #include 5 | #define rep(i,n) for(int i=0;i<(int)(n);i++) 6 | #define rep1(i,n) for(int i=1;i<=(int)(n);i++) 7 | #define all(c) c.begin(),c.end() 8 | #define pb push_back 9 | #define fs first 10 | #define sc second 11 | #define show(x) cout << #x << " = " << (x) << endl 12 | #define chmin(x,y) x=min(x,y) 13 | #define chmax(x,y) x=max(x,y) 14 | using namespace std; 15 | template ostream& operator<<(ostream& o,const pair &p){return o<<"("< ostream& operator<<(ostream& o,const vector &vc){o<<"{";for(const T& v:vc) o<; 20 | bool bit(int x,int i){return (x>>i)&1;} 21 | 22 | template 23 | vector operator+(const vector& a, const vector& b){ 24 | vector c = a; 25 | c.insert(c.end(),all(b)); 26 | return c; 27 | } 28 | 29 | struct edge{ 30 | int u,v,c; 31 | edge(int u,int v,int c):u(u),v(v),c(c){} 32 | // edge(){} 33 | friend ostream& operator<<(ostream &o,const edge& e){ 34 | return o<<"edge(" << e.u << "," << e.v << ", c = " << e.c << ")"; 35 | } 36 | 37 | }; 38 | 39 | struct TreeDecomp{ 40 | int V; //tree size 41 | int B; //max bag size ( = tw+1) 42 | vector> T; //tree-decomp 43 | vector> bags; 44 | 45 | TreeDecomp(){} 46 | TreeDecomp(int V,int B,const vector>& T, const vector>& bags):V(V),B(B),T(T),bags(bags){} 47 | }TD; 48 | 49 | /* 50 | return pair(a & !b ,b & !a); 51 | */ 52 | pair,vector> getdif(const vector& a, const vector& b){ 53 | //naive 54 | vector x,y; 55 | for(int v:a){ 56 | if(!binary_search(all(b),v)) x.pb(v); 57 | } 58 | for(int v:b){ 59 | if(!binary_search(all(a),v)) y.pb(v); 60 | } 61 | return make_pair(x,y); 62 | } 63 | 64 | int N,M; 65 | vector es; //edges 66 | vector ts; //terminals 67 | vector isTerminal; 68 | 69 | struct UnionFind{ 70 | int N; 71 | vector par; 72 | 73 | UnionFind(int N):N(N){ 74 | par.resize(N); 75 | rep(i,N) par[i]=i; 76 | } 77 | UnionFind(const vector& par):par(par){ 78 | N = par.size(); 79 | } 80 | int find(int x){ 81 | if(par[x]==x) return x; 82 | return par[x]=find(par[x]); 83 | } 84 | bool same(int x,int y){ 85 | return find(x)==find(y); 86 | } 87 | void unite(int x,int y){ 88 | x=find(x),y=find(y); 89 | if(x==y) return; 90 | if(x>y) swap(x,y); //roots have the smallest id 91 | par[y]=x; 92 | } 93 | void normalize(){ 94 | rep(i,N) par[i] = find(i); 95 | } 96 | }; 97 | UnionFind ins(UnionFind UF,int I){ 98 | // puts("---------ins--------"); 99 | int N = UF.N; 100 | // show(N); 101 | 102 | // show(I); 103 | vector& vs = UF.par; 104 | // show(vs); 105 | vector nvs(N+1); 106 | rep(i,N) nvs[(i vs; 116 | rep(i,N) if(UF.same(i,I)) vs.pb(i); 117 | if(vs.size() == 1){ //alone 118 | UF.N = -1; 119 | return UF; 120 | } 121 | int r = vs[0]==I ? vs[1] : vs[0]; 122 | 123 | vector nvs(N-1); 124 | rep(i,N-1){ 125 | int id = i=I) nvs[i]--; 132 | } 133 | return UnionFind(nvs); 134 | } 135 | UnionFind glue(UnionFind UF,int x,int y){ 136 | assert(x prevs; 161 | State(const UnionFind& UF,int cost,const vector& prevs): UF(UF),cost(cost),prevs(prevs){} 162 | State(const UnionFind& UF,int cost): UF(UF),cost(cost),prevs({}){} 163 | State(): UF(UnionFind(0)){} //defined dummy for map 164 | friend ostream& operator<<(ostream &o,const State& x){ 165 | return o<<"state: " << x.UF.par << " cost = " << x.cost; 166 | } 167 | }; 168 | 169 | struct Data{ 170 | int N; 171 | vector vs; 172 | vector> states; //states[s] = {(UF,cost)} 173 | 174 | Data(){ 175 | N = 0; 176 | vs = {}; 177 | states = {}; 178 | }; 179 | Data(const vector& vs, const vector>& states): vs(vs),states(states){ 180 | N = vs.size(); 181 | } 182 | // Data(const vector& vs): vs(vs){ 183 | // N = vs.size(); 184 | // states.resize(1<& vs = d.vs; 221 | auto& states = d.states; 222 | // show(states); 223 | 224 | int nN = N+1; 225 | vector nvs = vs; 226 | nvs.pb(v); 227 | sort(all(nvs)); 228 | 229 | int vid = -1; // index of v in nvs 230 | rep(i,nN) if(nvs[i] == v) vid = i; 231 | assert(vid != -1); 232 | 233 | vector> nstates(1<& vs = d.vs; 263 | auto& states = d.states; 264 | 265 | int nN = N-1; 266 | vector nvs; 267 | int eraseid = -1; 268 | rep(i,N){ 269 | if(vs[i] == v){ 270 | eraseid = i; 271 | }else{ 272 | nvs.pb(vs[i]); 273 | } 274 | } 275 | assert(eraseid != -1); 276 | 277 | vector> nstates(1<& vstate = nstates[s]; 280 | int ps = 0; 281 | rep(i,eraseid) if(bit(s,i)) ps |= 1< important_datas; 302 | 303 | Data introduce_edge(Data _d,int x,int y,int c){ 304 | int ox = x, oy = y; 305 | 306 | important_datas.pb(_d); 307 | auto& d = important_datas.back(); 308 | 309 | int N = d.N; 310 | vector& vs = d.vs; 311 | auto& states = d.states; 312 | 313 | vector nvs = vs; 314 | 315 | { //convert x,y to id in vs 316 | int xid = -1, yid = -1; 317 | rep(i,N){ 318 | if(vs[i]==x) xid = i; 319 | if(vs[i]==y) yid = i; 320 | } 321 | assert(xid != -1); 322 | assert(yid != -1); 323 | x = xid, y = yid; 324 | } 325 | 326 | vector> nstates(1<& vstate = nstates[s]; 329 | vstate = states[s]; //don't use edge 330 | if(bit(s,x) && bit(s,y)){ 331 | int xinUF = 0, yinUF = 0; 332 | rep(i,x) if(bit(s,i)) xinUF++; 333 | rep(i,y) if(bit(s,i)) yinUF++; 334 | for(State& state: states[s]){ 335 | vstate.pb( State(glue(state.UF,xinUF,yinUF), state.cost+c, {Prev(&state,ox,oy)} ) ); 336 | } 337 | rmc(vstate); 338 | } 339 | } 340 | return Data(nvs,nstates); 341 | } 342 | Data join(Data a,Data b){ 343 | assert(a.vs == b.vs); 344 | int N = a.N; 345 | vector& vs = a.vs; 346 | 347 | vector nvs = vs; 348 | 349 | vector> nstates(1<& vstate = nstates[s]; 352 | for(const State& sa: a.states[s]) for(const State& sb: b.states[s]){ 353 | vstate.pb(State(merge(sa.UF,sb.UF),sa.cost+sb.cost,sa.prevs+sb.prevs)); 354 | } 355 | rmc(vstate); 356 | } 357 | return Data(nvs,nstates); 358 | } 359 | 360 | map unintroduced_edges; //e,cost 361 | 362 | Data dfs(int v,int p=-1){ 363 | // printf("dfs %d,%d\n",v,p); 364 | vector dats; 365 | for(int u: TD.T[v]) if(u!=p){ 366 | Data d = dfs(u,v); 367 | auto vv = getdif(TD.bags[u],TD.bags[v]); 368 | for(int x:vv.fs) d = forget(d,x); 369 | for(int x:vv.sc) d = introduce(d,x); 370 | dats.pb(d); 371 | } 372 | if(dats.empty()){ //leaf 373 | Data d = leaf(); 374 | // show(TD.bags[v]); 375 | for(int x: TD.bags[v]) d = introduce(d,x); 376 | dats.pb(d); 377 | } 378 | while(dats.size()>1){ 379 | int K = dats.size(); 380 | Data nd = join(dats[K-2],dats[K-1]); 381 | rep(i,2) dats.pop_back(); 382 | dats.pb(nd); 383 | } 384 | Data& d = dats[0]; 385 | for(int x: TD.bags[v]) for(int y: TD.bags[v]) if(x& ansEdges){ 399 | for(Prev prev: state->prevs){ 400 | ansEdges.pb(P(prev.u,prev.v)); 401 | recover(prev.from,ansEdges); 402 | } 403 | } 404 | void validate(int ans, vector

ansEdges){ 405 | map e2c; 406 | rep(i,M) e2c[P(es[i].u,es[i].v)] = e2c[P(es[i].v,es[i].u)] = es[i].c; 407 | int sum = 0; 408 | for(P e:ansEdges){ 409 | sum += e2c[e]; 410 | } 411 | assert(ans == sum); 412 | 413 | UnionFind UF(N); 414 | for(P e:ansEdges){ 415 | UF.unite(e.fs,e.sc); 416 | } 417 | int T = ts.size(); 418 | bool isconnected = 1; 419 | rep(i,T){ 420 | if(!UF.same(ts[0],ts[i])) isconnected = 0; 421 | } 422 | assert(isconnected); 423 | 424 | set vs; 425 | for(P e:ansEdges){ 426 | vs.insert(e.fs); 427 | vs.insert(e.sc); 428 | } 429 | bool istree = vs.empty() || (vs.size() == ansEdges.size()+1); 430 | assert(istree); 431 | } 432 | 433 | 434 | vector

mySolve(){ 435 | // input(); 436 | // printf("B = %d, N = %d, M = %d, V = %d\n",TD.B,N,M,TD.V); 437 | // return 0; 438 | // long long Esum = 0; 439 | // rep(i,M){ 440 | // Esum += es[i].c; 441 | // } 442 | // show(Esum); 443 | // return 0; 444 | // puts("-----mySolve-----"); 445 | // show(N); 446 | // show(M); 447 | // show(es); 448 | // show(ts); 449 | // show(isTerminal); 450 | // show(TD.V); 451 | // show(TD.B); 452 | // show(TD.T); 453 | // show(TD.bags); 454 | 455 | int r = -1, lastv = -1; 456 | rep(x,TD.V){ 457 | for(int v: TD.bags[x]) if(binary_search(all(ts),v)){ 458 | r = x; 459 | lastv = v; 460 | } 461 | } 462 | assert(r != -1); 463 | 464 | TD.T.pb({r}); 465 | TD.T[r].pb({TD.V}); 466 | TD.bags.pb({lastv}); 467 | TD.V ++; 468 | 469 | rep(i,M){ 470 | int x = es[i].u; 471 | int y = es[i].v; 472 | int c = es[i].c; 473 | if(x>y) swap(x,y); 474 | unintroduced_edges[P(x,y)] = c; 475 | } 476 | 477 | Data d = dfs(TD.V-1); 478 | 479 | int ans = 1e9; 480 | State best; 481 | for(const auto& state: d.states[1]){ 482 | // show(state); 483 | if(ans > state.cost){ 484 | ans = state.cost; 485 | best = state; 486 | } 487 | } 488 | // show(ans); 489 | vector

ansEdges; 490 | recover(&best, ansEdges); 491 | // show(ansEdges); 492 | validate(ans,ansEdges); 493 | 494 | return ansEdges; 495 | } 496 | 497 | extern "C" { 498 | /* 499 | input: 500 | 501 | N: 502 | M: 503 | edges: x1 y1 c1 x2 y2 c2 ... xM yM cM 504 | T: num of terminals 505 | terminals: t1 t2 .. tT 506 | 507 | V: the number of vertices in tree-decomposition 508 | td: 509 | k1 v1 v2 .. v_{k1} 510 | k2 v1 v2 .. v_{k2} 511 | : 512 | kV v1 v2 .. v_{kV} 513 | 514 | tedges: 515 | x1 y1 516 | x2 y2 517 | : 518 | x_{K-1} y_{K-1} 519 | 520 | output: 521 | return K: the number of edges used 522 | ans: 523 | x1 y1 x2 y2 .. x_K y_K 524 | */ 525 | int solve(int N, int M, int* edges, int T, int* terminals, int V, int* td, int* tedges, int* ans){ 526 | ::N = N; 527 | ::M = M; 528 | es.clear(); 529 | ts.clear(); 530 | isTerminal.clear(); 531 | rep(i,M){ 532 | es.pb(edge(edges[i*3],edges[i*3+1],edges[i*3+2])); 533 | } 534 | isTerminal = vector(N,false); 535 | rep(i,T){ 536 | ts.pb(terminals[i]); 537 | isTerminal[ts.back()] = 1; 538 | } 539 | sort(all(ts)); 540 | 541 | vector> Tree(V),bags(V); 542 | 543 | int I = 0; 544 | int B = 0; 545 | rep(i,V){ 546 | int K = td[I++]; 547 | chmax(B,K); 548 | rep(k,K){ 549 | bags[i].pb(td[I++]); 550 | } 551 | sort(all(bags[i])); 552 | } 553 | rep(i,V-1){ 554 | int u = tedges[i*2], v = tedges[i*2+1]; 555 | Tree[u].pb(v); 556 | Tree[v].pb(u); 557 | } 558 | 559 | TD = TreeDecomp(V,B,Tree,bags); 560 | 561 | vector

ansEdges = mySolve(); 562 | 563 | int K = ansEdges.size(); 564 | rep(i,K){ 565 | ans[i*2] = ansEdges[i].fs; 566 | ans[i*2+1] = ansEdges[i].sc; 567 | } 568 | return K; 569 | } 570 | } 571 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | 3 | use std::ops::*; 4 | use std::collections::{BinaryHeap, BTreeMap, BTreeSet}; 5 | use std::cmp::Ordering; 6 | use std::cell::Cell; 7 | 8 | #[macro_use] 9 | pub mod util { 10 | 11 | pub struct OnDrop { 12 | f: Box 13 | } 14 | 15 | impl OnDrop { 16 | #[inline] 17 | pub fn new(f: F) -> OnDrop { 18 | OnDrop { f: Box::new(f) } 19 | } 20 | } 21 | 22 | impl Drop for OnDrop { 23 | #[inline] 24 | fn drop(&mut self) { 25 | (*self.f)(); 26 | } 27 | } 28 | 29 | pub static mut PROFILER: *mut Vec<(&str, &(f64, usize))> = 0 as *mut Vec<_>; 30 | 31 | #[macro_export] 32 | macro_rules! profile { 33 | ($id:ident) => {} 34 | } 35 | 36 | // #[macro_export] 37 | // macro_rules! profile { 38 | // ($id:ident) => { 39 | // static mut __PROF: (f64, usize) = (0.0, 0); 40 | // unsafe { 41 | // if __PROF.1 == 0 { 42 | // if $crate::util::PROFILER.is_null() { 43 | // $crate::util::PROFILER = Box::into_raw(Box::new(Vec::new())); 44 | // } 45 | // (*$crate::util::PROFILER).push((stringify!($id), &__PROF)); 46 | // } 47 | // __PROF.1 += 1; 48 | // } 49 | // let t = ::std::time::SystemTime::now(); 50 | // let _b = $crate::util::OnDrop::new(move || { 51 | // let d = t.elapsed().unwrap(); 52 | // let s = d.as_secs() as f64 + d.subsec_nanos() as f64 * 1e-9; 53 | // unsafe { 54 | // __PROF.0 += s; 55 | // } 56 | // }); 57 | // } 58 | // } 59 | 60 | pub fn write_profile(w: &mut W) where W: ::std::io::Write { 61 | if unsafe { PROFILER.is_null() } { 62 | return; 63 | } 64 | let mut ps: Vec<_> = unsafe { (*PROFILER).clone() }; 65 | ps.sort_by(|&(_, a), &(_, b)| b.partial_cmp(&a).unwrap()); 66 | let _ = writeln!(w, "########## Profile ##########"); 67 | for (id, &(t, c)) in ps { 68 | let _ = writeln!(w, "{}:\t{:.3}\t{}", id, t, c); 69 | } 70 | let _ = writeln!(w, "#############################"); 71 | } 72 | 73 | } 74 | 75 | pub type W = i32; 76 | pub type G = Vec>; 77 | pub type E = (usize, usize); 78 | pub type TD = (Vec>, Vec<(usize, usize)>); 79 | 80 | pub const INF: W = std::i32::MAX; 81 | 82 | pub trait SetMin { 83 | fn setmin(&mut self, v: Self) -> bool; 84 | } 85 | impl SetMin for T where T: PartialOrd { 86 | fn setmin(&mut self, v: T) -> bool { 87 | *self > v && { *self = v; true } 88 | } 89 | } 90 | pub trait SetMax { 91 | fn setmax(&mut self, v: Self) -> bool; 92 | } 93 | impl SetMax for T where T: PartialOrd { 94 | fn setmax(&mut self, v: T) -> bool { 95 | *self < v && { *self = v; true } 96 | } 97 | } 98 | 99 | #[derive(Clone, Debug)] 100 | pub struct UnionFind { 101 | /// size / parent 102 | ps: Vec>, 103 | pub is_root: Vec 104 | } 105 | 106 | impl UnionFind { 107 | pub fn new(n: usize) -> UnionFind { 108 | UnionFind { ps: vec![Cell::new(1); n], is_root: vec![true; n] } 109 | } 110 | pub fn find(&self, x: usize) -> usize { 111 | if self.is_root[x] { x } 112 | else { 113 | let p = self.find(self.ps[x].get()); 114 | self.ps[x].set(p); 115 | p 116 | } 117 | } 118 | pub fn unite(&mut self, x: usize, y: usize) { 119 | let mut x = self.find(x); 120 | let mut y = self.find(y); 121 | if x == y { return } 122 | if self.ps[x].get() < self.ps[y].get() { 123 | ::std::mem::swap(&mut x, &mut y); 124 | } 125 | *self.ps[x].get_mut() += self.ps[y].get(); 126 | self.ps[y].set(x); 127 | self.is_root[y] = false; 128 | } 129 | pub fn same(&self, x: usize, y: usize) -> bool { 130 | self.find(x) == self.find(y) 131 | } 132 | pub fn size(&self, x: usize) -> usize { 133 | self.ps[self.find(x)].get() 134 | } 135 | } 136 | 137 | #[derive(Clone, Debug)] 138 | pub struct InitVec { 139 | version: u32, 140 | init: T, 141 | data: Vec<(T, u32)> 142 | } 143 | 144 | impl InitVec { 145 | pub fn new(v: T, n: usize) -> InitVec { 146 | InitVec { version: 0, init: v.clone(), data: vec![(v, 0); n] } 147 | } 148 | pub fn init(&mut self) { 149 | if self.version == u32::max_value() { 150 | for v in &mut self.data { 151 | v.1 = 0; 152 | } 153 | self.version = 1; 154 | } else { 155 | self.version += 1; 156 | } 157 | } 158 | #[inline] 159 | pub fn len(&self) -> usize { 160 | self.data.len() 161 | } 162 | } 163 | 164 | impl Index for InitVec { 165 | type Output = T; 166 | #[inline] 167 | fn index(&self, i: usize) -> &T { 168 | if self.data[i].1 == self.version { 169 | &self.data[i].0 170 | } else { 171 | &self.init 172 | } 173 | } 174 | } 175 | 176 | impl IndexMut for InitVec { 177 | #[inline] 178 | fn index_mut(&mut self, i: usize) -> &mut T { 179 | if self.data[i].1 != self.version { 180 | self.data[i].1 = self.version; 181 | self.data[i].0 = self.init.clone(); 182 | } 183 | &mut self.data[i].0 184 | } 185 | } 186 | 187 | #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)] 188 | pub struct BitSet { 189 | data: Vec 190 | } 191 | 192 | impl BitSet { 193 | 194 | pub fn new(n: usize) -> Self { 195 | BitSet { data: vec![0; (n + 63) / 64] } 196 | } 197 | 198 | #[inline] 199 | pub fn set(&mut self, i: usize, b: bool) { 200 | if b { 201 | self.data[i / 64] |= 1 << (i & 63) 202 | } else { 203 | self.data[i / 64] &= !(1 << (i & 63)) 204 | } 205 | } 206 | 207 | pub fn intersect(&self, other: &Self) -> bool { 208 | for i in 0..self.data.len() { 209 | if self.data[i] & other.data[i] != 0 { 210 | return true; 211 | } 212 | } 213 | false 214 | } 215 | 216 | pub fn count(&self) -> usize { 217 | let mut c = 0; 218 | for &a in &self.data { 219 | c += u64::count_ones(a); 220 | } 221 | c as usize 222 | } 223 | 224 | } 225 | 226 | impl Index for BitSet { 227 | type Output = bool; 228 | #[inline] 229 | fn index(&self, i: usize) -> &bool { 230 | if self.data[i / 64] >> (i & 63) & 1 == 0 { 231 | &false 232 | } else { 233 | &true 234 | } 235 | } 236 | } 237 | 238 | impl<'a> BitAnd for &'a BitSet { 239 | type Output = BitSet; 240 | fn bitand(self, other: &BitSet) -> BitSet { 241 | BitSet { data: self.data.iter().zip(other.data.iter()).map(|(&a, &b)| a & b).collect() } 242 | } 243 | } 244 | 245 | impl<'a> BitOr for &'a BitSet { 246 | type Output = BitSet; 247 | fn bitor(self, other: &BitSet) -> BitSet { 248 | BitSet { data: self.data.iter().zip(other.data.iter()).map(|(&a, &b)| a | b).collect() } 249 | } 250 | } 251 | 252 | impl<'a> BitXor for &'a BitSet { 253 | type Output = BitSet; 254 | fn bitxor(self, other: &BitSet) -> BitSet { 255 | BitSet { data: self.data.iter().zip(other.data.iter()).map(|(&a, &b)| a ^ b).collect() } 256 | } 257 | } 258 | 259 | 260 | #[derive(Debug)] 261 | enum Modify { 262 | /// (u, v, w): v with N(v)={u,w} is contracted to u. 263 | Contract(usize, usize, usize), 264 | /// (u, v, Nv): uv is included and v is contracted to u. Nv is the set of neighbors w of v such that c(vw)) 266 | } 267 | 268 | pub struct Reduction { 269 | orig_n: usize, 270 | t0: usize, 271 | pub g: G, 272 | pub ts: Vec, 273 | pub td: Option, 274 | ids: Vec, 275 | w0: W, 276 | modify: Vec 277 | } 278 | 279 | impl Reduction { 280 | 281 | fn size(g: &Vec>, is_t: &Vec) -> (usize, usize, usize) { 282 | let mut n = 0; 283 | let mut m = 0; 284 | let mut t = 0; 285 | for (i, a) in g.iter().enumerate() { 286 | if a.len() > 0 { 287 | n += 1; 288 | m += a.len(); 289 | if is_t[i] { 290 | t += 1; 291 | } 292 | } 293 | } 294 | (n, m / 2, t) 295 | } 296 | 297 | fn get_ts(g: &Vec>, is_t: &Vec) -> (Vec, Vec) { 298 | let n = g.len(); 299 | let mut ts = vec![]; 300 | let mut id = vec![!0; n]; 301 | for u in 0..n { 302 | if is_t[u] && g[u].len() > 0 { 303 | id[u] = ts.len(); 304 | ts.push(u); 305 | } 306 | } 307 | (ts, id) 308 | } 309 | 310 | // Include all the edges of weight zero. 311 | fn weight0(g: &mut Vec>, is_t: &mut Vec, modify: &mut Vec) -> bool { 312 | let n = g.len(); 313 | let mut modified = false; 314 | for u in 0..n { 315 | if let Some((&v, _)) = g[u].iter().find(|&(_, &w)| w == 0) { 316 | is_t[v] |= is_t[u]; 317 | is_t[u] = false; 318 | let mut xs = vec![]; 319 | for (x, w) in std::mem::replace(&mut g[u], BTreeMap::new()) { 320 | g[x].remove(&u); 321 | if x != v && g[v].entry(x).or_insert(INF).setmin(w) { 322 | g[x].insert(v, w); 323 | xs.push(x); 324 | } 325 | } 326 | modify.push(Modify::Include(v, u, xs)); 327 | modified = true; 328 | } 329 | } 330 | modified 331 | } 332 | 333 | // Lightweight reduction which runs in linear time. 334 | fn light(g: &mut Vec>, is_t: &mut Vec, modify: &mut Vec, w0: &mut W) -> bool { 335 | profile!(light); 336 | let n = g.len(); 337 | let mut modified = false; 338 | let mut t_count = is_t.iter().filter(|b| **b).count(); 339 | for u in 0..n { 340 | if t_count <= 1 { 341 | break; 342 | } 343 | if g[u].len() == 0 { 344 | } else if g[u].len() == 1 { 345 | // When terminal u has degree one, we can include the incident edge. 346 | // When non-terminal u has degree one, we can remove it. 347 | let fs = std::mem::replace(&mut g[u], BTreeMap::new()); 348 | for (v, w) in fs { 349 | if is_t[u] { 350 | if is_t[v] { 351 | t_count -= 1; 352 | } 353 | is_t[u] = false; 354 | is_t[v] = true; 355 | modify.push(Modify::Include(v, u, vec![])); 356 | *w0 += w; 357 | } 358 | g[v].remove(&u); 359 | modified = true; 360 | } 361 | } else if g[u].len() == 2 && !is_t[u] { 362 | // When non-terminal u has degree two, we can contract it. 363 | let fs: Vec<_> = std::mem::replace(&mut g[u], BTreeMap::new()).into_iter().collect(); 364 | let (v1, w1) = fs[0]; 365 | let (v2, w2) = fs[1]; 366 | g[v1].remove(&u); 367 | g[v2].remove(&u); 368 | modified = true; 369 | if g[v1].entry(v2).or_insert(INF).setmin(w1 + w2) { 370 | g[v2].insert(v1, w1 + w2); 371 | modify.push(Modify::Contract(v1, u, v2)); 372 | } 373 | } else if is_t[u] { 374 | // When the edge uv connecting two terminal u and v has the smallest weight among all the edges incident to u, we can include it. 375 | let min_w = g[u].iter().map(|(_, &w)| w).min().unwrap(); 376 | let mut v = !0; 377 | for (&a, &w) in &g[u] { 378 | if w == min_w && is_t[a] { 379 | v = a; 380 | break; 381 | } 382 | } 383 | if v != !0 { 384 | t_count -= 1; 385 | is_t[u] = false; 386 | *w0 += min_w; 387 | let mut xs = vec![]; 388 | for (x, w) in std::mem::replace(&mut g[u], BTreeMap::new()) { 389 | g[x].remove(&u); 390 | if x != v && g[v].entry(x).or_insert(INF).setmin(w) { 391 | g[x].insert(v, w); 392 | xs.push(x); 393 | } 394 | } 395 | modify.push(Modify::Include(v, u, xs)); 396 | modified = true; 397 | } 398 | } 399 | } 400 | modified 401 | } 402 | 403 | // s(u,v) := bottleneck distance from u to v in the distance graph on A+u+v. 404 | // When s(u,v)>, is_t: &Vec) -> bool { 406 | profile!(sd); 407 | let mut del = vec![]; 408 | { 409 | let n = g.len(); 410 | let (ts, _) = Reduction::get_ts(g, is_t); 411 | let mut tid = vec![!0; n]; 412 | for t in 0..ts.len() { 413 | tid[ts[t]] = t; 414 | } 415 | // Perturbation for tie-breaking. 416 | let g: Vec> = (0..n).map(|u| g[u].iter().map(|(&v, &w)| (v, ((w as i64) << 32) - if is_t[u] { 2 } else { 1 } - if is_t[v] { 2 } else { 1 })).collect()).collect(); 417 | let mut max_w = 0; 418 | for u in 0..n { 419 | for &(_, w) in &g[u] { 420 | max_w.setmax(w); 421 | } 422 | } 423 | let mut dist_t = vec![vec![std::i64::MAX; n]; ts.len()]; 424 | let mut gt = vec![vec![]; ts.len()]; 425 | let mut que = BinaryHeap::new(); 426 | { 427 | profile!(dist_t); 428 | for i in 0..ts.len() { 429 | let dist = &mut dist_t[i]; 430 | dist[ts[i]] = 0; 431 | que.push((0, ts[i])); 432 | while let Some((d, u)) = que.pop() { 433 | let d = -d; 434 | if dist[u] != d { 435 | continue; 436 | } 437 | for &(v, w) in &g[u] { 438 | let d2 = d + w; 439 | if d2 < max_w && dist[v].setmin(d2) { 440 | que.push((-d2, v)); 441 | } 442 | } 443 | } 444 | for &t in &ts { 445 | if t == ts[i] { 446 | continue; 447 | } 448 | if dist[t] < max_w { 449 | gt[i].push((dist[t], t)); 450 | } 451 | gt[i].sort(); 452 | } 453 | } 454 | } 455 | let mut dist = InitVec::new(std::i64::MAX, n); 456 | for s in 0..n { 457 | if g[s].len() == 0 { 458 | continue; 459 | } 460 | let mut d_max = std::i64::MIN; 461 | let mut adj = vec![]; 462 | for &(v, w) in &g[s] { 463 | if s < v { 464 | d_max.setmax(w); 465 | adj.push(v); 466 | } 467 | } 468 | if adj.len() == 0 { 469 | continue; 470 | } 471 | dist.init(); 472 | dist[s] = 0; 473 | que.push((0, s)); 474 | while let Some((d, u)) = que.pop() { 475 | let d = -d; 476 | if d != dist[u] { 477 | continue; 478 | } 479 | let i = tid[u]; 480 | if i != !0 { 481 | for &v in &adj { 482 | dist[v].setmin(d.max(dist_t[i][v])); 483 | } 484 | for &(w, t) in >[i] { 485 | if w >= d_max { 486 | break; 487 | } 488 | let d2 = d.max(w); 489 | if dist[t].setmin(d2) { 490 | que.push((-d2, t)); 491 | } 492 | } 493 | } else { 494 | for &(v, w) in &g[u] { 495 | let d2 = d + w; 496 | if d2 < d_max && dist[v].setmin(d2) { 497 | que.push((-d2, v)); 498 | } 499 | } 500 | } 501 | } 502 | for &(v, w) in &g[s] { 503 | if s < v && w > dist[v] { 504 | del.push((s, v)); 505 | } 506 | } 507 | } 508 | } 509 | for &(u, v) in &del { 510 | g[u].remove(&v); 511 | g[v].remove(&u); 512 | } 513 | del.len() > 0 514 | } 515 | 516 | // Let T be a minimum spanning tree. 517 | // By removing an edge uv\in T, we split T into T_u and T_v, and terminals A into A_u and A_v. 518 | // If d(u, A_u+x) + c(uv) + d(v, A_v+y) <= c(xy) holds for every chord xy between T_u and T_v, we can include uv. 519 | fn nsc(g: &mut Vec>, is_t: &mut Vec, modify: &mut Vec, w0: &mut W) -> bool { 520 | profile!(nsc); 521 | let n = g.len(); 522 | let mut fs = vec![]; 523 | for u in 0..n { 524 | for (&v, &w) in &g[u] { 525 | if u < v { 526 | fs.push((w, if is_t[u] { 0 } else { 1 } + if is_t[v] { 0 } else { 1 }, u, v)); 527 | } 528 | } 529 | } 530 | fs.sort(); 531 | let mut uf = UnionFind::new(n); 532 | let mut mst = vec![vec![]; n]; 533 | for (w, _, u, v) in fs { 534 | if !uf.same(u, v) { 535 | uf.unite(u, v); 536 | mst[u].push((v, w)); 537 | mst[v].push((u, w)); 538 | } 539 | } 540 | let mut parent = vec![!0; n]; 541 | let mut depth = vec![!0; n]; 542 | let mut r = !0; 543 | for u in 0..n { 544 | if mst[u].len() > 0 { 545 | r = u; 546 | break; 547 | } 548 | } 549 | if r == !0 { 550 | return false; 551 | } 552 | let mut root_to_leaf = vec![]; 553 | let mut p = 0; 554 | root_to_leaf.push(r); 555 | depth[r] = 0; 556 | while p < root_to_leaf.len() { 557 | let u = root_to_leaf[p]; 558 | p += 1; 559 | for &(v, w) in &mst[u] { 560 | if depth[v] == !0 { 561 | depth[v] = depth[u] + w; 562 | parent[v] = u; 563 | root_to_leaf.push(v); 564 | } 565 | } 566 | } 567 | let (ts, id) = Reduction::get_ts(g, is_t); 568 | let mut dist_t = vec![vec![INF; n]; ts.len()]; 569 | for i in 0..ts.len() { 570 | let mut que = BinaryHeap::new(); 571 | let dist = &mut dist_t[i]; 572 | dist[ts[i]] = 0; 573 | que.push((0, ts[i])); 574 | while let Some((d, u)) = que.pop() { 575 | let d = -d; 576 | if dist[u] != d { 577 | continue; 578 | } 579 | for (&v, &w) in &g[u] { 580 | let d2 = d + w; 581 | if dist[v].setmin(d2) { 582 | que.push((-d2, v)); 583 | } 584 | } 585 | } 586 | } 587 | let mut ts_below = vec![vec![]; n]; 588 | for &u in root_to_leaf.iter().rev() { 589 | if is_t[u] { 590 | ts_below[u].push(id[u]); 591 | } 592 | let v = parent[u]; 593 | if v != !0 { 594 | let a = ts_below[u].clone(); 595 | ts_below[v].extend(a); 596 | } 597 | } 598 | let mut min_below = vec![INF; n]; 599 | let mut min_above = vec![INF; n]; 600 | let mut is_below = InitVec::new(false, ts.len()); 601 | for &u in &root_to_leaf { 602 | is_below.init(); 603 | for &b in &ts_below[u] { 604 | is_below[b] = true; 605 | } 606 | for i in 0..ts.len() { 607 | if is_below[i] { 608 | min_below[u].setmin(dist_t[i][u]); 609 | } else { 610 | min_above[u].setmin(dist_t[i][parent[u]]); 611 | } 612 | } 613 | } 614 | let mut ok: Vec<_> = (0..n).map(|u| parent[u] != !0 && min_below[u] < INF && min_above[u] < INF).collect(); 615 | for u in 0..n { 616 | for (&v, &w) in &g[u] { 617 | if v == parent[u] || u == parent[v] || u < v { 618 | continue; 619 | } 620 | let mut x = u; 621 | let mut y = v; 622 | while x != y { 623 | if depth[x] < depth[y] { 624 | y = parent[y]; 625 | } else { 626 | x = parent[x]; 627 | } 628 | } 629 | let lca = x; 630 | let mut x = u; 631 | let mut y = v; 632 | while x != y { 633 | if depth[x] < depth[y] { 634 | if ok[y] { 635 | let c = depth[y] - depth[parent[y]]; 636 | let d_above = depth[u] - depth[lca] + depth[parent[y]] - depth[lca]; 637 | let d_below = depth[v] - depth[y]; 638 | if d_above.min(min_above[y]) + d_below.min(min_below[y]) + c > w { 639 | ok[y] = false; 640 | } 641 | } 642 | y = parent[y]; 643 | } else { 644 | if ok[x] { 645 | let c = depth[x] - depth[parent[x]]; 646 | let d_above = depth[v] - depth[lca] + depth[parent[x]] - depth[lca]; 647 | let d_below = depth[u] - depth[x]; 648 | if d_above.min(min_above[x]) + d_below.min(min_below[x]) + c > w { 649 | ok[x] = false; 650 | } 651 | } 652 | x = parent[x]; 653 | } 654 | } 655 | } 656 | } 657 | let mut modified = false; 658 | for &u in root_to_leaf.iter().rev() { 659 | if ok[u] { 660 | modified = true; 661 | let v = parent[u]; 662 | let w = depth[u] - depth[v]; 663 | is_t[v] |= is_t[u]; 664 | is_t[u] = false; 665 | let mut xs = vec![]; 666 | for (x, w) in std::mem::replace(&mut g[u], BTreeMap::new()) { 667 | g[x].remove(&u); 668 | if x != v && g[v].entry(x).or_insert(INF).setmin(w) { 669 | g[x].insert(v, w); 670 | xs.push(x); 671 | } 672 | } 673 | modify.push(Modify::Include(v, u, xs)); 674 | *w0 += w; 675 | } 676 | } 677 | modified 678 | } 679 | 680 | fn deg3(g: &mut Vec>, is_t: &Vec) -> bool { 681 | profile!(deg3); 682 | let n = g.len(); 683 | let mut modified = false; 684 | let mut dist = InitVec::new(INF, n); 685 | // Compute d(s,t) on G-deleted, or return ub if the distance is at least ub. 686 | let mut dist = |g: &Vec>, deleted: &InitVec, s: &[usize], t: usize, ub: W| -> W { 687 | dist.init(); 688 | let mut que = BinaryHeap::new(); 689 | for &u in s { 690 | dist[u] = 0; 691 | que.push((0, u)); 692 | } 693 | while let Some((d, u)) = que.pop() { 694 | let d = -d; 695 | if u == t { 696 | return d; 697 | } 698 | if dist[u] != d { 699 | continue; 700 | } 701 | for (&v, &w) in &g[u] { 702 | let d2 = d + w; 703 | if d2 < ub && !deleted[v] && dist[v].setmin(d2) { 704 | que.push((-d2, v)); 705 | } 706 | } 707 | } 708 | ub 709 | }; 710 | let mut deleted = InitVec::new(false, n); 711 | for u in 0..n { 712 | if g[u].len() == 3 && !is_t[u] { 713 | let gu: Vec<_> = g[u].iter().map(|(&u, &w)| (u, w)).collect(); 714 | for i in 0..3 { 715 | let (mut p, mut up) = gu[i]; 716 | let (x, ux) = gu[(i + 1) % 3]; 717 | let (y, uy) = gu[(i + 2) % 3]; 718 | deleted.init(); 719 | deleted[u] = true; 720 | let xp = dist(g, &deleted, &[x], p, ux + up + 1); 721 | if xp > ux + up { 722 | continue; 723 | } 724 | let yp = dist(g, &deleted, &[y], p, uy + up + 1); 725 | if yp > uy + up { 726 | continue; 727 | } 728 | // u has three neighbors {p, x, y} and there are shortest paths from p to x and p to y both avoiding u. 729 | // Let OPT be the set of edges contained in every optimal solution. 730 | // Suppose that up is in OPT. Then ux and uy are also in OPT. 731 | let xy = dist(g, &deleted, &[x], y, ux + uy); 732 | if xp + yp + xy - xp.max(yp).max(xy) <= ux + uy + up { 733 | // Instead of using {up, ux, uy}, we can use MST of {p, x, y}. 734 | modified = true; 735 | g[u].remove(&p); 736 | g[p].remove(&u); 737 | break; 738 | } else { 739 | let mut del = false; 740 | loop { 741 | if dist(g, &deleted, &[x, y], p, up + 1) <= up { 742 | // If there exists a path from {x,y} to p of length at most up, we can replace up by the path. 743 | del = true; 744 | break; 745 | } 746 | if is_t[p] { 747 | break; 748 | } 749 | // If p is not a terminal, p must have degree at least two in OPT. 750 | deleted[p] = true; 751 | let mut ps = vec![]; 752 | for (&q, &pq) in &g[p] { 753 | // If there exists a path from {x, y} to q of length at most max(up, pq), we can replace tp or pq by the path. 754 | if ps.len() < 2 && !deleted[q] && dist(g, &deleted, &[x, y], q, up.max(pq) + 1) > up.max(pq) { 755 | ps.push((q, pq)); 756 | } 757 | } 758 | if ps.len() > 1 { 759 | break; 760 | } else if ps.len() == 1 { 761 | // If there is only one candidate q, p has degree two in OPT. 762 | // We repeat the process by setting p<-q. 763 | p = ps[0].0; 764 | up += ps[0].1; 765 | } else { 766 | del = true; 767 | break; 768 | } 769 | } 770 | if del { 771 | modified = true; 772 | let p = gu[i].0; 773 | g[u].remove(&p); 774 | g[p].remove(&u); 775 | break; 776 | } 777 | } 778 | } 779 | } 780 | } 781 | modified 782 | } 783 | 784 | pub fn reduce(g: &G, ts: &Vec, td: &Option) -> Self { 785 | let n = g.len(); 786 | let t0 = ts[0]; 787 | let mut g2 = vec![BTreeMap::new(); n]; 788 | let mut is_t = vec![false; n]; 789 | for &t in ts { 790 | is_t[t] = true; 791 | } 792 | for u in 0..n { 793 | for &(v, w) in &g[u] { 794 | g2[u].entry(v).or_insert(INF).setmin(w); 795 | } 796 | } 797 | let mut g = g2; 798 | let mut modify = vec![]; 799 | let mut w0 = 0; 800 | { 801 | let (n, m, t) = Reduction::size(&g, &is_t); 802 | if Reduction::weight0(&mut g, &mut is_t, &mut modify) { 803 | let (n2, m2, t2) = Reduction::size(&g, &is_t); 804 | eprintln!("weight0: ({}, {}, {}) -> ({}, {}, {})", n, m, t, n2, m2, t2); 805 | } 806 | } 807 | loop { 808 | let (n, m, t) = Reduction::size(&g, &is_t); 809 | // print_input(&g.iter().map(|a| a.iter().map(|(&u, &w)| (u, w)).collect()).collect(), &(0..is_t.len()).filter(|&i| is_t[i]).collect()); 810 | if t <= 1 { 811 | eprintln!("reduce: ({}, {}, {}) -> ({}, {}, {})", n, m, t, 0, 0, 0); 812 | break; 813 | } 814 | if Reduction::light(&mut g, &mut is_t, &mut modify, &mut w0) { 815 | let (n2, m2, t2) = Reduction::size(&g, &is_t); 816 | eprintln!("light: ({}, {}, {}) -> ({}, {}, {})", n, m, t, n2, m2, t2); 817 | continue; 818 | } 819 | if Reduction::sd(&mut g, &is_t) { 820 | let (n2, m2, t2) = Reduction::size(&g, &is_t); 821 | eprintln!("sd: ({}, {}, {}) -> ({}, {}, {})", n, m, t, n2, m2, t2); 822 | continue; 823 | } 824 | if Reduction::nsc(&mut g, &mut is_t, &mut modify, &mut w0) { 825 | let (n2, m2, t2) = Reduction::size(&g, &is_t); 826 | eprintln!("nsc: ({}, {}, {}) -> ({}, {}, {})", n, m, t, n2, m2, t2); 827 | continue; 828 | } 829 | if Reduction::deg3(&mut g, &is_t) { 830 | let (n2, m2, t2) = Reduction::size(&g, &is_t); 831 | eprintln!("deg3: ({}, {}, {}) -> ({}, {}, {})", n, m, t, n2, m2, t2); 832 | continue; 833 | } 834 | break; 835 | } 836 | let mut ids = vec![]; 837 | let mut name = vec![!0; n]; 838 | for u in 0..n { 839 | if g[u].len() > 0 { 840 | name[u] = ids.len(); 841 | ids.push(u); 842 | } 843 | } 844 | let mut ts = vec![]; 845 | for t in 0..n { 846 | if is_t[t] && name[t] != !0 { 847 | ts.push(name[t]); 848 | } 849 | } 850 | let mut g2 = vec![vec![]; ids.len()]; 851 | for u in 0..ids.len() { 852 | for (&v, &w) in &g[ids[u]] { 853 | g2[u].push((name[v], w)); 854 | } 855 | } 856 | for u in 0..n { 857 | for (&v, &w) in &g[u] { 858 | assert!(g[v][&u] == w); 859 | } 860 | } 861 | let td = if let Some(ref td) = *td { 862 | for m in modify.iter().rev() { 863 | match *m { 864 | Modify::Contract(u, v, _) | Modify::Include(u, v, _) => { 865 | name[v] = name[u]; 866 | }, 867 | } 868 | } 869 | let bs: Vec<_> = td.0.iter().map(|bag| { 870 | let mut vs = vec![]; 871 | for &v in bag { 872 | if name[v] != !0 { 873 | vs.push(name[v]); 874 | } 875 | } 876 | vs.sort(); 877 | vs.dedup(); 878 | vs 879 | }).collect(); 880 | Some((bs, td.1.clone())) 881 | } else { 882 | None 883 | }; 884 | util::write_profile(&mut std::io::stderr()); 885 | Self { orig_n: n, t0, g: g2, ts, ids, modify, w0, td } 886 | } 887 | 888 | pub fn restore(&self, w: W, es: Vec) -> (W, Vec) { 889 | let mut g = vec![BTreeSet::new(); self.orig_n]; 890 | for (u, v) in es { 891 | let u = self.ids[u]; 892 | let v = self.ids[v]; 893 | g[u].insert(v); 894 | g[v].insert(u); 895 | } 896 | for modify in self.modify.iter().rev() { 897 | match *modify { 898 | Modify::Contract(u, v, w) => { 899 | if g[u].contains(&w) { 900 | g[u].remove(&w); 901 | g[w].remove(&u); 902 | g[u].insert(v); 903 | g[v].insert(u); 904 | g[w].insert(v); 905 | g[v].insert(w); 906 | } 907 | }, 908 | Modify::Include(u, v, ref ws) => { 909 | for &w in ws { 910 | if g[u].contains(&w) { 911 | g[u].remove(&w); 912 | g[w].remove(&u); 913 | g[v].insert(w); 914 | g[w].insert(v); 915 | } 916 | } 917 | g[u].insert(v); 918 | g[v].insert(u); 919 | } 920 | } 921 | } 922 | let mut visited = vec![false; self.orig_n]; 923 | let mut stack = vec![]; 924 | visited[self.t0] = true; 925 | stack.push(self.t0); 926 | while let Some(u) = stack.pop() { 927 | for &v in &g[u] { 928 | if visited[v].setmax(true) { 929 | stack.push(v); 930 | } 931 | } 932 | } 933 | let mut es = vec![]; 934 | for u in 0..self.orig_n { 935 | for &v in &g[u] { 936 | if visited[u] && visited[v] && u < v { 937 | es.push((u, v)); 938 | } 939 | } 940 | } 941 | (w + self.w0, es) 942 | } 943 | 944 | } 945 | 946 | #[derive(Copy, Clone, Debug)] 947 | struct Data { 948 | v: usize, 949 | cost: i64, 950 | prev: (usize, usize) // leaf: (!0, !0), move: (v, !0), merge: (x, y) 951 | } 952 | 953 | struct IntersectIter<'a> { 954 | d1: &'a[Data], 955 | d2: &'a[Data], 956 | p: usize, 957 | q: usize, 958 | } 959 | 960 | /// returns all (x, y)'s with d1[x].v == d2[y].v 961 | fn intersect<'a>(d1: &'a[Data], d2: &'a[Data]) -> IntersectIter<'a> { 962 | IntersectIter { d1, d2, p: 0, q: 0 } 963 | } 964 | 965 | impl<'a> Iterator for IntersectIter<'a> { 966 | type Item = (usize, usize); 967 | #[inline] 968 | fn next(&mut self) -> Option<(usize, usize)> { 969 | while self.p < self.d1.len() && self.q < self.d2.len() { 970 | match self.d1[self.p].v.cmp(&self.d2[self.q].v) { 971 | Ordering::Equal => { 972 | self.p += 1; 973 | self.q += 1; 974 | return Some((self.p - 1, self.q - 1)); 975 | }, 976 | Ordering::Less => { 977 | self.p += 1; 978 | }, 979 | Ordering::Greater => { 980 | self.q += 1; 981 | } 982 | } 983 | } 984 | None 985 | } 986 | } 987 | 988 | struct BitTree { 989 | ts: Vec, 990 | root: usize, 991 | } 992 | 993 | struct SubTree { 994 | i_and: BitSet, 995 | v_or: BitSet, 996 | p: usize, 997 | i_pos: usize, 998 | cs: [usize; 2] 999 | } 1000 | 1001 | impl BitTree { 1002 | fn new() -> Self { 1003 | BitTree { ts: vec![], root: !0 } 1004 | } 1005 | fn insert(&mut self, i: BitSet, v: BitSet, p: usize) { 1006 | if self.root == !0 { 1007 | self.new_leaf(i, v, p); 1008 | self.root = 0; 1009 | } else { 1010 | let root = self.root; 1011 | self.root = self._insert(i, v, p, root, 0); 1012 | } 1013 | } 1014 | fn new_leaf(&mut self, i: BitSet, v: BitSet, p: usize) -> usize { 1015 | let i_pos = i.data.len() * 64; 1016 | self.ts.push(SubTree { 1017 | i_and: i, 1018 | v_or: v, 1019 | p, 1020 | i_pos, 1021 | cs: [!0, !0] 1022 | }); 1023 | self.ts.len() - 1 1024 | } 1025 | fn _insert(&mut self, i: BitSet, v: BitSet, p: usize, x: usize, i_pos: usize) -> usize { 1026 | if self.ts[x].i_pos == i_pos { 1027 | let j = if i[i_pos] { 1028 | 1 1029 | } else { 1030 | 0 1031 | }; 1032 | let c = self.ts[x].cs[j]; 1033 | self.ts[x].i_and = &self.ts[x].i_and & &i; 1034 | self.ts[x].v_or = &self.ts[x].v_or | &v; 1035 | self.ts[x].cs[j] = self._insert(i, v, p, c, i_pos + 1); 1036 | x 1037 | } else if self.ts[x].i_and[i_pos] != i[i_pos] { 1038 | let leaf = self.new_leaf(i.clone(), v.clone(), p); 1039 | let tmp = SubTree { 1040 | i_and: &i & &self.ts[x].i_and, 1041 | v_or: &v | &self.ts[x].v_or, 1042 | p: !0, 1043 | i_pos, 1044 | cs: if i[i_pos] { 1045 | [x, leaf] 1046 | } else { 1047 | [leaf, x] 1048 | } 1049 | }; 1050 | self.ts.push(tmp); 1051 | self.ts.len() - 1 1052 | } else { 1053 | self._insert(i, v, p, x, i_pos + 1) 1054 | } 1055 | } 1056 | fn find(&self, i: &BitSet, v: &BitSet) -> Vec { 1057 | if self.root == !0 { 1058 | return vec![]; 1059 | } 1060 | let mut ps = vec![]; 1061 | self._find(i, v, self.root, &mut ps); 1062 | ps 1063 | } 1064 | fn _find(&self, i: &BitSet, v: &BitSet, x: usize, ps: &mut Vec) { 1065 | if self.ts[x].i_and.intersect(&i) || !self.ts[x].v_or.intersect(&v) { 1066 | return; 1067 | } else if self.ts[x].i_pos == i.data.len() * 64 { 1068 | ps.push(self.ts[x].p); 1069 | } else { 1070 | self._find(i, v, self.ts[x].cs[0], ps); 1071 | if !i[self.ts[x].i_pos] { 1072 | self._find(i, v, self.ts[x].cs[1], ps); 1073 | } 1074 | } 1075 | } 1076 | } 1077 | 1078 | pub mod pruned { 1079 | 1080 | use ::*; 1081 | 1082 | pub fn solve(g: &G, ts: &Vec) -> (W, Vec) { 1083 | if ts.len() <= 1 { 1084 | return (0, vec![]); 1085 | } 1086 | let n = g.len(); 1087 | let div = (1i64 << 32) / n as i64; 1088 | // Perturbation for tie-breaking. 1089 | let g: Vec> = (0..n).map(|u| g[u].iter().map(|&(v, w)| (v, (w as i64) << 32 | (u + v) as i64 % div)).collect()).collect(); 1090 | const INF: i64 = std::i64::MAX; 1091 | let T = ts.len(); 1092 | let mut tid = vec![!0; n]; 1093 | for t in 0..T { 1094 | tid[ts[t]] = t; 1095 | } 1096 | let mut all = BitSet::new(T); 1097 | for i in 0..T { 1098 | all.set(i, true); 1099 | } 1100 | let mut i_set = BTreeSet::new(); 1101 | let mut ongoing = BTreeMap::new(); 1102 | for i in 0..T { 1103 | let mut bit = BitSet::new(T); 1104 | bit.set(i, true); 1105 | i_set.insert((1, bit.clone())); 1106 | ongoing.insert(bit, vec![Data { v: ts[i], cost: 0, prev: (!0, !0) }]); 1107 | } 1108 | let mut min = INF; 1109 | let mut min_x = !0; 1110 | let mut min_prev = (!0, !0); 1111 | let mut bit_tree = BitTree::new(); 1112 | let mut bits = vec![]; 1113 | let mut bit_counts = vec![]; 1114 | let mut offsets = vec![0]; 1115 | let mut data = vec![]; 1116 | let mut total_size = 0; 1117 | let mut process = 0; 1118 | while i_set.len() > 0 { 1119 | let (i_count, i) = i_set.iter().next().unwrap().clone(); 1120 | i_set.remove(&(i_count, i.clone())); 1121 | let crt = ongoing.remove(&i).unwrap(); 1122 | let i_count = i.count(); 1123 | if process.setmax(i_count) { 1124 | eprintln!("Finished = {}/{}", process - 1, T / 2); 1125 | eprintln!("total = {}", total_size); 1126 | eprintln!("subsets = {}", bits.len()); 1127 | } 1128 | // eprintln!("{:?}: {:?}", (0..T).filter(|&t| i[t]).map(|t| ts[t]).collect::>(), crt.iter().map(|c| (c.v, c.cost >> 32)).collect::>()); 1129 | let mut dist = vec![INF; n]; // dist[r] := minimum steiner tree for i rooted at r. 1130 | let mut ub = vec![INF; n]; // No optimal subtrees for T-i contain vertices at distance < ub[u] from u. 1131 | let mut prev = vec![(!0, !0); n]; 1132 | let mut valid = vec![false; n]; 1133 | { 1134 | profile!(trace); 1135 | // Construct steiner trees for i by tracing prev. 1136 | // If u is contained in every tree, set ub[u] <- min_tree maximum length of an induced degree-2 path from u to the root. 1137 | let mut cs: Vec<_> = (0..crt.len()).map(|i| (crt[i].cost, i)).collect(); 1138 | cs.sort(); 1139 | let mut count = vec![0; n]; 1140 | let mut stack = vec![]; 1141 | let mut valid_count = 0; 1142 | for (_, i) in cs { 1143 | let c = &crt[i]; 1144 | let d = c.cost; 1145 | if dist[c.v] < d { 1146 | continue; 1147 | } 1148 | dist[c.v] = d; 1149 | valid[c.v] = true; 1150 | prev[c.v] = c.prev; 1151 | valid_count += 1; 1152 | count[c.v] += 1; 1153 | ub[c.v] = 0; 1154 | if c.prev.0 != !0 { 1155 | let (x, y) = c.prev; 1156 | stack.push((x, 0, 0)); 1157 | stack.push((y, 0, 0)); 1158 | while let Some((x, c, w)) = stack.pop() { 1159 | let Data { cost, prev: (x, y), .. } = data[x]; 1160 | if x != !0 { 1161 | if y != !0 { 1162 | stack.push((x, 0, w)); 1163 | stack.push((y, 0, w)); 1164 | } else { 1165 | let v2 = data[x].v; 1166 | let c2 = c + cost - data[x].cost; 1167 | let w2 = w.max(c2); 1168 | dist[v2].setmin(d); 1169 | count[v2] += 1; 1170 | ub[v2].setmin(w2); 1171 | stack.push((x, c2, w2)); 1172 | } 1173 | } 1174 | } 1175 | } 1176 | } 1177 | for u in 0..n { 1178 | if count[u] < valid_count { 1179 | ub[u] = 0; 1180 | } 1181 | } 1182 | } 1183 | let mut s = !0; 1184 | { 1185 | profile!(dist); 1186 | // Compute dist by Dijkstra's algorithm. 1187 | // For speeding up, we stop when it visits a terminal or all the neighbors of a terminal. 1188 | let mut adj_count = vec![0; T]; 1189 | let mut que = BinaryHeap::new(); 1190 | for u in 0..n { 1191 | if dist[u] < INF { 1192 | que.push((-dist[u], u)); 1193 | } 1194 | } 1195 | 'dij: while let Some((d, u)) = que.pop() { 1196 | let d = -d; 1197 | if d != dist[u] { 1198 | continue; 1199 | } 1200 | if tid[u] != !0 && !i[tid[u]] { 1201 | s = u; 1202 | break; 1203 | } 1204 | let ok = valid[u]; 1205 | for &(v, w) in &g[u] { 1206 | let d2 = d + w; 1207 | if dist[v].setmin(d2) { 1208 | que.push((-d2, v)); 1209 | valid[v] = ok; 1210 | prev[v] = (u, !0); 1211 | } else if dist[v] == d2 && !ok { 1212 | valid[v] = false; 1213 | } 1214 | if tid[v] != !0 && !i[tid[v]] && T - i_count > 1 { 1215 | adj_count[tid[v]] += 1; 1216 | if adj_count[tid[v]] == g[v].len() { 1217 | s = v; 1218 | break 'dij; 1219 | } 1220 | } 1221 | } 1222 | } 1223 | } 1224 | if T - i_count > 1 { 1225 | profile!(prune); 1226 | // Propagate ub by Dijkstra's algorithm. 1227 | let mut que = BinaryHeap::new(); 1228 | for u in 0..n { 1229 | if ub[u] > 0 { 1230 | que.push((ub[u], u)); 1231 | } 1232 | } 1233 | while let Some((d, u)) = que.pop() { 1234 | if d != ub[u] { 1235 | continue; 1236 | } 1237 | for &(v, w) in &g[u] { 1238 | let d2 = d - w; 1239 | if ub[v].setmax(d2) { 1240 | que.push((d2, v)); 1241 | } 1242 | } 1243 | } 1244 | // Let V_d := {v | dist[v] >= d && ub[v] <= 0}. 1245 | // Let atmost := max d s.t. T-i is connected on G[V_d]. 1246 | // Then every optimal steiner tree for T-i contains a vertex v with dist[v] <= atmost. 1247 | // Therefore the current steiner tree rooted at v is valid only when dist[v] <= atmost. 1248 | let mut atmost = -1; 1249 | if (0..T).find(|&t| !i[t] && ub[ts[t]] > 0).is_none() { 1250 | let mut count_t = 0; 1251 | let mut min_d = vec![-1; n]; 1252 | min_d[s] = dist[s]; 1253 | que.push((dist[s], s)); 1254 | let mut stack = vec![]; 1255 | 'cut: while let Some((d, u)) = que.pop() { 1256 | if d != min_d[u] { 1257 | continue; 1258 | } 1259 | stack.push(u); 1260 | while let Some(u) = stack.pop() { 1261 | if tid[u] != !0 && !i[tid[u]] { 1262 | count_t += 1; 1263 | if count_t == T - i_count { 1264 | atmost = d; 1265 | break 'cut; 1266 | } 1267 | } 1268 | for &(v, _) in &g[u] { 1269 | if ub[v] > 0 { 1270 | continue; 1271 | } 1272 | let d2 = d.min(dist[v]); 1273 | if min_d[v].setmax(d2) { 1274 | if d == d2 { 1275 | stack.push(v); 1276 | } else { 1277 | que.push((d2, v)); 1278 | } 1279 | } 1280 | } 1281 | } 1282 | } 1283 | } 1284 | for u in 0..n { 1285 | if dist[u] > atmost { // || ub[u] > 0 { 1286 | valid[u] = false; 1287 | } 1288 | } 1289 | } 1290 | if valid.iter().find(|&&v| v).is_none() { 1291 | continue; 1292 | } 1293 | let mut di: Vec<_> = (0..n).filter(|&v| valid[v]).map(|v| Data { v, cost: dist[v], prev: prev[v] }).collect(); 1294 | let mut id = vec![!0; n]; 1295 | for x in 0..di.len() { 1296 | id[di[x].v] = total_size + x; 1297 | } 1298 | for a in &mut di { 1299 | if a.prev.0 != !0 && a.prev.1 == !0 { 1300 | a.prev.0 = id[a.prev.0]; 1301 | } 1302 | } 1303 | profile!(merge); 1304 | let mut valid_bit = BitSet::new(n); 1305 | for u in 0..n { 1306 | if valid[u] { 1307 | valid_bit.set(u, true); 1308 | } 1309 | } 1310 | for q in bit_tree.find(&i, &valid_bit) { // Find all j s.t. i & j == 0 and valids[i] & valids[j] != 0. 1311 | if i_count * 2 + bit_counts[q] > T { 1312 | continue; 1313 | } 1314 | let j = &bits[q]; 1315 | let dj = &data[offsets[q]..offsets[q + 1]]; 1316 | let tmp: Vec = intersect(&di, dj).map(|(x, y)| Data { v: di[x].v, cost: di[x].cost + dj[y].cost, prev: (total_size + x, offsets[q] + y)}).collect(); 1317 | let k = &i | j; 1318 | let mut merged = false; 1319 | if let Some(dk) = ongoing.get_mut(&k) { 1320 | let mut dk2 = vec![]; 1321 | let mut x = 0; 1322 | let mut y = 0; 1323 | while x < dk.len() || y < tmp.len() { 1324 | let v1 = if x < dk.len() { 1325 | dk[x].v 1326 | } else { 1327 | n 1328 | }; 1329 | let v2 = if y < tmp.len() { 1330 | tmp[y].v 1331 | } else { 1332 | n 1333 | }; 1334 | match v1.cmp(&v2) { 1335 | Ordering::Equal => { 1336 | if dk[x].cost <= tmp[y].cost { 1337 | dk2.push(dk[x]); 1338 | } else { 1339 | dk2.push(tmp[y]); 1340 | } 1341 | x += 1; 1342 | y += 1; 1343 | }, 1344 | Ordering::Less => { 1345 | dk2.push(dk[x]); 1346 | x += 1; 1347 | }, 1348 | Ordering::Greater => { 1349 | dk2.push(tmp[y]); 1350 | y += 1; 1351 | } 1352 | } 1353 | } 1354 | *dk = dk2; 1355 | merged = true; 1356 | } 1357 | if !merged { 1358 | if k.count() * 2 <= T { 1359 | i_set.insert((k.count(), k.clone())); 1360 | } 1361 | ongoing.insert(k, tmp); 1362 | } 1363 | } 1364 | let j = &all ^ &i; 1365 | if let Some(ref dj) = ongoing.get(&j) { 1366 | for (x, y) in intersect(&di, dj) { 1367 | if min.setmin(di[x].cost + dj[y].cost) { 1368 | min_x = total_size + x; 1369 | min_prev = dj[y].prev; 1370 | } 1371 | } 1372 | } 1373 | let size = di.len(); 1374 | if i_count * 3 <= T { 1375 | bit_tree.insert(i.clone(), valid_bit, bits.len()); 1376 | } 1377 | bits.push(i); 1378 | bit_counts.push(i_count); 1379 | data.extend(di); 1380 | total_size += size; 1381 | offsets.push(total_size); 1382 | } 1383 | 1384 | if min == INF { 1385 | return (0, vec![]); 1386 | } 1387 | assert!(min != INF); 1388 | util::write_profile(&mut std::io::stderr()); 1389 | eprintln!("total = {}", total_size); 1390 | eprintln!("subsets = {}", bits.len()); 1391 | let mut es = vec![]; 1392 | let mut stack = vec![min_x]; 1393 | if min_prev.0 != !0 { 1394 | stack.push(min_prev.0); 1395 | } 1396 | if min_prev.1 != !0 { 1397 | stack.push(min_prev.1); 1398 | } 1399 | while let Some(x) = stack.pop() { 1400 | if data[x].prev.0 != !0 { 1401 | stack.push(data[x].prev.0); 1402 | if data[x].prev.1 != !0 { 1403 | stack.push(data[x].prev.1); 1404 | } else { 1405 | es.push((data[x].v, data[data[x].prev.0].v)); 1406 | } 1407 | } 1408 | } 1409 | ((min >> 32) as W, es) 1410 | } 1411 | 1412 | } 1413 | 1414 | pub fn validate(g: &G, ts: &Vec, w: W, es: &Vec) -> bool { 1415 | let n = g.len(); 1416 | let mut w2 = 0; 1417 | let mut g2 = vec![BTreeMap::new(); n]; 1418 | for u in 0..n { 1419 | for &(v, w) in &g[u] { 1420 | g2[u].entry(v).or_insert(INF).setmin(w); 1421 | } 1422 | } 1423 | let mut st = vec![vec![]; n]; 1424 | for &(u, v) in es { 1425 | st[u].push(v); 1426 | st[v].push(u); 1427 | if let Some(&w) = g2[u].get(&v) { 1428 | w2 += w as i64; 1429 | } else { 1430 | eprintln!("illegal edge"); 1431 | return false; 1432 | } 1433 | } 1434 | if w2 != w as i64 { 1435 | eprintln!("wrong value: {} vs {}", w, w2); 1436 | return false; 1437 | } 1438 | let mut visited = vec![false; n]; 1439 | let mut stack = vec![]; 1440 | visited[ts[0]] = true; 1441 | stack.push(ts[0]); 1442 | while let Some(u) = stack.pop() { 1443 | for &v in &st[u] { 1444 | if !visited[v] { 1445 | visited[v] = true; 1446 | stack.push(v); 1447 | } 1448 | } 1449 | } 1450 | for &t in ts { 1451 | if !visited[t] { 1452 | eprintln!("not connected"); 1453 | return false; 1454 | } 1455 | } 1456 | return true; 1457 | } 1458 | --------------------------------------------------------------------------------