1 #define _CRT_SECURE_NO_WARNINGS
2 /*
3 5 5 8
4 4 3 6831
5 1 3 4583
6 0 0 6592
7 0 1 3063
8 3 3 4975
9 1 3 2049
10 4 2 2104
11 2 2 781
12 */
13 #include <iostream>
14 #include <vector>
15 #include <algorithm>
16 #include <cstdio>
17 using namespace std;
18
19 const int maxn = 10000 + 10;
20 const int maxR = 50000;
21 const int INF = 9999999;
22 int par[maxn]; //父亲, 当par[x] = x时,x是所在的树的根
23 int Rank[maxn]; //树的高度
24 int N, M, R;
25 int V, E;
26 int x[maxR], y[maxR], d[maxR];
27
28 struct edge
29 {
30 int u, v, cost;
31 edge(int u = 0, int v = 0, int cost = 0) : u(u), v(v), cost(cost) {}
32 };
33
34 bool comp(const edge& e1, const edge& e2) {
35 return e1.cost < e2.cost;
36 }
37
38 edge es[maxn];
39
40 //并查集实现-高效的判断是否属于同一个连通分量。
41 void init_union_find(int n);
42 int find(int x);
43 void unite(int x, int y);
44 bool same(int x, int y);
45
46 //最小生成树
47 void input();
48 int kruskal(); //最小生成树算法
49 //最大权森林
50 void solve();
51
52 //初始化n个元素
53 void init_union_find(int n)
54 {
55 for (int i = 0; i < n; i++) {
56 par[i] = i;
57 Rank[i] = 0;
58 }
59 }
60
61 //查询树的根
62 int find(int x) {
63 if (par[x] == x) {
64 return x;
65 }
66 else {
67 return par[x] = find(par[x]);
68 }
69 }
70
71 //合并x和y所属集合
72 void unite(int x, int y) {
73 x = find(x);
74 y = find(y);
75 if (x == y) return;
76
77 if (Rank[x] < Rank[y]) {
78 par[x] = y;
79 }
80 else {
81 par[y] = x;
82 if (Rank[x] == Rank[y]) Rank[x]++; //如果x,y的树高相同,就让x的树高+1
83 }
84 }
85
86 //判断x和y是否属于同一个集合
87 bool same(int x, int y) {
88 return find(x) == find(y);
89 }
90
91 void input()
92 {
93 scanf("%d%d%d", &N, &M, &R);
94 for (int i = 0; i < R; i++) {
95 scanf("%d%d%d", &x[i], &y[i], &d[i]);
96 }
97 }
98
99 int kruskal()
100 {
101 sort(es, es + E, comp); //按照edge.cost的顺序从小到大排序
102 init_union_find(V); //将并查集初始化
103 int res = 0;
104 for (int i = 0; i < E; i++) {
105 edge e = es[i];
106 if (!same(e.u, e.v)) {
107 unite(e.u, e.v);
108 res += e.cost;
109 }
110 }
111 return res;
112 }
113
114 void solve()
115 {
116 V = N + M;
117 E = R;
118 for (int i = 0; i < R; i++) {
119 es[i] = edge(x[i], N + y[i], -d[i]);
120 }
121 int res = kruskal();
122 //cout << "Debug" << res << endl;
123 cout << 10000 * (N + M) + res << endl; //kruskal结果是-d[i]
124 }
125
126 int main()
127 {
128 input();
129 solve();
130 return 0;
131 }