Submission #1226353
Source Code Expand
/+ dub.sdl:
name "A"
dependency "dcomp" version=">=0.6.0"
+/
import std.stdio, std.algorithm, std.range, std.conv;
import std.typecons;
// import dcomp.foundation, dcomp.scanner;
// import dcomp.datastructure.unionfind;
// import dcomp.graph.lca;
int main() {
auto sc = new Scanner(stdin);
int n, m;
sc.read(n, m);
int[] a = new int[m];
int[] b = new int[m];
long[] c = new long[m];
foreach (i; 0..m) {
sc.read(a[i], b[i], c[i]);
a[i]--; b[i]--;
}
int[] idx = iota(m).array;
idx.sort!((x, y) => c[x] < c[y]);
auto uf = new UnionFind(n);
alias Edge = Tuple!(int, "to", long, "cost");
auto g = new Edge[][n];
long sm;
foreach (i; idx) {
if (uf.same(a[i], b[i])) continue;
uf.merge(a[i], b[i]);
sm += c[i];
g[a[i]] ~= Edge(b[i], c[i]);
g[b[i]] ~= Edge(a[i], c[i]);
}
auto lca = lcaInfo(g);
int lg = lca.anc.length.to!int;
long[][] ma = new long[][](lg, n);
void dfs(int p, int b) {
foreach (e; g[p]) {
if (e.to == b) continue;
ma[0][e.to] = e.cost;
dfs(e.to, p);
}
}
dfs(0, -1);
foreach (i; 1..lg) {
foreach (j; 0..n) {
ma[i][j] = ma[i-1][j];
if (lca.anc[i-1][j] != -1) {
ma[i][j] = max(ma[i][j], ma[i-1][lca.anc[i-1][j]]);
}
}
}
long getMa(int s, int t) {
int di = lca.dps[s]-lca.dps[t];
long ans = -1;
foreach_reverse (i; 0..lg) {
if (2^^i <= di) {
di -= 2^^i;
ans = max(ans, ma[i][s]);
s = lca.anc[i][s];
}
}
return ans;
}
int q;
sc.read(q);
foreach (i; 0..q) {
int s, t;
sc.read(s, t); s--; t--;
int u = lca.lca(s, t);
// writeln(s, " ", t, " ", u, " ", getMa(s, u), " ", getMa(t, u));
writeln(sm - max(getMa(s, u), getMa(t, u)));
}
return 0;
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/foundation.d */
// module dcomp.foundation;
//fold(for old compiler)
static if (__VERSION__ <= 2070) {
template fold(fun...) if (fun.length >= 1) {
auto fold(R, S...)(R r, S seed) {
import std.algorithm : reduce;
static if (S.length < 2) {
return reduce!fun(seed, r);
} else {
import std.typecons : tuple;
return reduce!fun(tuple(seed), r);
}
}
}
unittest {
import std.stdio;
auto l = [1, 2, 3, 4, 5];
assert(l.fold!"a+b"(10) == 25);
}
}
version (X86) static if (__VERSION__ < 2071) {
int bsf(ulong v) {
foreach (i; 0..64) {
if (v & (1UL << i)) return i;
}
return -1;
}
int bsr(ulong v) {
foreach_reverse (i; 0..64) {
if (v & (1UL << i)) return i;
}
return -1;
}
int popcnt(ulong v) {
int c = 0;
foreach (i; 0..64) {
if (v & (1UL << i)) c++;
}
return c;
}
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/scanner.d */
// module dcomp.scanner;
class Scanner {
import std.stdio : File;
import std.conv : to;
import std.range : front, popFront, array, ElementType;
import std.array : split;
import std.traits : isSomeChar, isStaticArray, isArray;
import std.algorithm : map;
File f;
this(File f) {
this.f = f;
}
char[512] lineBuf;
char[] line;
private bool succ() {
import std.range.primitives : empty, front, popFront;
import std.ascii : isWhite;
while (true) {
while (!line.empty && line.front.isWhite) {
line.popFront;
}
if (!line.empty) break;
if (f.eof) return false;
line = lineBuf[];
f.readln(line);
}
return true;
}
private bool readSingle(T)(ref T x) {
import std.algorithm : findSplitBefore;
import std.string : strip;
import std.conv : parse;
if (!succ()) return false;
static if (isArray!T) {
alias E = ElementType!T;
static if (isSomeChar!E) {
//string or char[10] etc
//todo optimize
auto r = line.findSplitBefore(" ");
x = r[0].strip.dup;
line = r[1];
} else {
auto buf = line.split.map!(to!E).array;
static if (isStaticArray!T) {
//static
assert(buf.length == T.length);
}
x = buf;
line.length = 0;
}
} else {
x = line.parse!T;
}
return true;
}
int read(T, Args...)(ref T x, auto ref Args args) {
if (!readSingle(x)) return 0;
static if (args.length == 0) {
return 1;
} else {
return 1 + read(args);
}
}
}
unittest {
import std.path : buildPath;
import std.file : tempDir;
import std.algorithm : equal;
import std.stdio : File;
string fileName = buildPath(tempDir, "kyuridenanmaida.txt");
auto fout = File(fileName, "w");
fout.writeln("1 2 3");
fout.writeln("ab cde");
fout.writeln("1.0 1.0 2.0");
fout.close;
Scanner sc = new Scanner(File(fileName, "r"));
int a;
int[2] b;
char[2] c;
string d;
double e;
double[] f;
sc.read(a, b, c, d, e, f);
assert(a == 1);
assert(equal(b[], [2, 3]));
assert(equal(c[], "ab"));
assert(equal(d, "cde"));
assert(e == 1.0);
assert(equal(f, [1.0, 2.0]));
}
unittest {
import std.path : buildPath;
import std.file : tempDir;
import std.algorithm : equal;
import std.stdio : File, writeln;
import std.datetime;
string fileName = buildPath(tempDir, "kyuridenanmaida.txt");
auto fout = File(fileName, "w");
foreach (i; 0..1_000_000) {
fout.writeln(3*i, " ", 3*i+1, " ", 3*i+2);
}
fout.close;
writeln("Scanner Speed Test(3*1,000,000 int)");
StopWatch sw;
sw.start;
Scanner sc = new Scanner(File(fileName, "r"));
foreach (i; 0..500_000) {
int a, b, c;
sc.read(a, b, c);
assert(a == 3*i);
assert(b == 3*i+1);
assert(c == 3*i+2);
}
foreach (i; 500_000..700_000) {
int[3] d;
sc.read(d);
int a = d[0], b = d[1], c = d[2];
assert(a == 3*i);
assert(b == 3*i+1);
assert(c == 3*i+2);
}
foreach (i; 700_000..1_000_000) {
int[] d;
sc.read(d);
assert(d.length == 3);
int a = d[0], b = d[1], c = d[2];
assert(a == 3*i);
assert(b == 3*i+1);
assert(c == 3*i+2);
}
writeln(sw.peek.msecs, "ms");
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/graph/lca.d */
// module dcomp.graph.lca;
struct LCAInfo {
int[] dps;
int[][] anc;
this(int n) {
import core.bitop : bsr;
int lg = n.bsr;
if ((2^^lg) < n) lg++;
dps = new int[n];
anc = new int[][](lg, n);
}
}
LCAInfo lcaInfo(T)(T g) {
import std.conv : to;
const int n = g.length.to!int;
auto info = LCAInfo(n);
with(info) {
int lg = anc.length.to!int;
void dfs(int p, int b, int nowDps) {
anc[0][p] = b;
dps[p] = nowDps;
foreach (e; g[p]) {
int d = e.to;
if (d == b) continue;
dfs(d, p, nowDps+1);
}
}
dfs(0, -1, 0);
foreach (i; 1..lg) {
foreach (j; 0..n) {
anc[i][j] = (anc[i-1][j] == -1) ? -1 : anc[i-1][anc[i-1][j]];
}
}
}
return info;
}
int lca(in LCAInfo lca, int l, int r) {
import std.algorithm : swap;
import std.conv : to;
int lg = lca.anc.length.to!int;
with (lca) {
if (dps[l] < dps[r]) swap(l, r);
int di = dps[l]-dps[r];
foreach_reverse (i; 0..lg) {
if (di < 2^^i) continue;
di -= 2^^i;
l = anc[i][l];
}
if (l == r) return l;
foreach_reverse (i; 0..lg) {
if (anc[i][l] == anc[i][r]) continue;
l = anc[i][l];
r = anc[i][r];
}
}
return lca.anc[0][l];
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/datastructure/unionfind.d */
// module dcomp.datastructure.unionfind;
struct UnionFind {
import std.algorithm : map, swap, each;
import std.range : iota, array;
int[] id; // group id
int[][] groups; // group list
int count; // group count
this(int n) {
id = iota(n).array;
groups = iota(n).map!(a => [a]).array;
count = n;
}
void merge(int a, int b) {
if (same(a, b)) return;
count--;
int x = id[a], y = id[b];
if (groups[x].length < groups[y].length) swap(x, y);
groups[y].each!(a => id[a] = x);
groups[x] ~= groups[y];
groups[y] = [];
}
int[] group(int i) {
return groups[id[i]];
}
bool same(int a, int b) {
return id[a] == id[b];
}
}
unittest {
import std.algorithm : equal, sort;
auto uf = UnionFind(5);
assert(!uf.same(1, 3));
assert(uf.same(0, 0));
uf.merge(3, 2);
uf.merge(1, 1);
uf.merge(4, 2);
uf.merge(4, 3);
assert(uf.count == 3);
assert(uf.id[2] == uf.id[3]);
assert(uf.id[2] == uf.id[4]);
assert(equal(uf.group(0), [0]));
assert(equal(uf.group(1), [1]));
assert(equal(sort(uf.group(2)), [2, 3, 4]));
}
unittest {
import std.datetime, std.stdio, std.range;
// speed check
writeln("UnionFind Speed Test");
StopWatch sw;
sw.start;
UnionFind uf;
// line
uf = UnionFind(1_000_000);
foreach (i; 1..1_000_000) {
uf.merge(i-1, i);
}
// line(reverse)
uf = UnionFind(1_000_000);
foreach_reverse (i; 1..1_000_000) {
uf.merge(i-1, i);
}
// binary tree
uf = UnionFind(1_000_000);
foreach (lg; 1..20) {
int len = 1<<lg;
foreach (i; iota(0, 1_000_000-len/2, len)) {
uf.merge(i, i+len/2);
}
}
sw.stop;
writeln(sw.peek.msecs, "ms");
}
Submission Info
Submission Time |
|
Task |
A - Graph |
User |
yosupo |
Language |
D (LDC 0.17.0) |
Score |
700 |
Code Size |
10760 Byte |
Status |
AC |
Exec Time |
238 ms |
Memory |
12796 KB |
Judge Result
Set Name |
Sample |
subtask1 |
subtask2 |
All |
Score / Max Score |
0 / 0 |
200 / 200 |
300 / 300 |
200 / 200 |
Status |
|
|
|
|
Set Name |
Test Cases |
Sample |
sample_1.txt, sample_2.txt |
subtask1 |
sample_2.txt, subtask_1_1.txt, subtask_1_10.txt, subtask_1_11.txt, subtask_1_2.txt, subtask_1_3.txt, subtask_1_4.txt, subtask_1_5.txt, subtask_1_6.txt, subtask_1_7.txt, subtask_1_8.txt, subtask_1_9.txt |
subtask2 |
sample_1.txt, sample_2.txt, subtask_1_1.txt, subtask_1_10.txt, subtask_1_11.txt, subtask_1_2.txt, subtask_1_3.txt, subtask_1_4.txt, subtask_1_5.txt, subtask_1_6.txt, subtask_1_7.txt, subtask_1_8.txt, subtask_1_9.txt, subtask_2_1.txt, subtask_2_2.txt, subtask_2_3.txt, subtask_2_4.txt, subtask_2_5.txt, subtask_2_6.txt, subtask_2_7.txt, subtask_2_8.txt |
All |
sample_1.txt, sample_2.txt, sample_1.txt, sample_2.txt, subtask_1_1.txt, subtask_1_10.txt, subtask_1_11.txt, subtask_1_2.txt, subtask_1_3.txt, subtask_1_4.txt, subtask_1_5.txt, subtask_1_6.txt, subtask_1_7.txt, subtask_1_8.txt, subtask_1_9.txt, subtask_2_1.txt, subtask_2_2.txt, subtask_2_3.txt, subtask_2_4.txt, subtask_2_5.txt, subtask_2_6.txt, subtask_2_7.txt, subtask_2_8.txt, subtask_3_1.txt, subtask_3_2.txt, subtask_3_3.txt, subtask_3_4.txt, subtask_3_5.txt, subtask_3_6.txt, subtask_3_7.txt, subtask_3_8.txt |
Case Name |
Status |
Exec Time |
Memory |
sample_1.txt |
AC |
1 ms |
256 KB |
sample_2.txt |
AC |
1 ms |
256 KB |
subtask_1_1.txt |
AC |
2 ms |
256 KB |
subtask_1_10.txt |
AC |
90 ms |
5372 KB |
subtask_1_11.txt |
AC |
1 ms |
256 KB |
subtask_1_2.txt |
AC |
20 ms |
3196 KB |
subtask_1_3.txt |
AC |
178 ms |
9852 KB |
subtask_1_4.txt |
AC |
6 ms |
1532 KB |
subtask_1_5.txt |
AC |
6 ms |
1532 KB |
subtask_1_6.txt |
AC |
46 ms |
3964 KB |
subtask_1_7.txt |
AC |
176 ms |
11260 KB |
subtask_1_8.txt |
AC |
6 ms |
2940 KB |
subtask_1_9.txt |
AC |
9 ms |
3324 KB |
subtask_2_1.txt |
AC |
179 ms |
11004 KB |
subtask_2_2.txt |
AC |
178 ms |
11132 KB |
subtask_2_3.txt |
AC |
179 ms |
10620 KB |
subtask_2_4.txt |
AC |
181 ms |
10108 KB |
subtask_2_5.txt |
AC |
8 ms |
3452 KB |
subtask_2_6.txt |
AC |
14 ms |
2940 KB |
subtask_2_7.txt |
AC |
48 ms |
4732 KB |
subtask_2_8.txt |
AC |
179 ms |
9852 KB |
subtask_3_1.txt |
AC |
238 ms |
10876 KB |
subtask_3_2.txt |
AC |
237 ms |
11644 KB |
subtask_3_3.txt |
AC |
65 ms |
4476 KB |
subtask_3_4.txt |
AC |
72 ms |
3964 KB |
subtask_3_5.txt |
AC |
152 ms |
6524 KB |
subtask_3_6.txt |
AC |
195 ms |
10236 KB |
subtask_3_7.txt |
AC |
238 ms |
12796 KB |
subtask_3_8.txt |
AC |
238 ms |
12028 KB |