@gym - 101137K@ Knights of the Old Republic


@description@

Given N points of a map M of edges.
Each point has two attributes Ai, Bi, Ai means you need at least two soldiers to capture the point, put a soldier to the point i spent Bi needs.
Each edge has an attribute Ci, if the number of soldiers represents two endpoints of the edge and> = Ci, then this edge was opened up (i.e., by the free edge of soldiers).

Soldiers do not die. Seeking to capture all the points and minimum cost.

Input
The first line contains two integers n, m (1 ≤ n, m ≤ 300000).
Next n lines of two integers ai and bi (0 ≤ ai, bi ≤ 1000000).
Next m lines of three integers si, fi ci described with an edge (si, fi) (1 ≤ si, fi ≤ n, 0 ≤ ci ≤ 1000000).

Output
output an integer representing the minimum cost.

Example
standard input
3 2
10 5
20 10
10 3
1 2 22
2 3 200
standard output
140

@solution@

At a final situation, for communication with a block, its contribution to the answer should be min {bi} * max {max {ai}, max {cj}}.
Because I want to put at least max {max {ai}, max {cj}} so many soldiers in order to ensure communication with and capture all the points, it is better to put in direct communication block this minimum cost point there.

When the communication block corresponding to the same point set, max {cj} should be as small as possible in order to obtain a better answer.
Max {cj} In this communication block communicates with minimal, which is obviously a minimum spanning tree (refer to the algorithmic process kruskal).

Continue the analysis. When a communication block max {ai, cj} ck greater than its adjacent one edge of k, I k added to this edge not be more clearly inferior (max {ai, cj} unchanged, min {b} but may smaller).

You can also get a more restrictive: when a communication block max {cj} ck greater than its adjacent one edge of k, k added this edge not still more inferior.
Accuracy, simply, is A * B + C * D> = min (A, C) * max (B, D). If the B <= D, then min (A, C) * max (B, D) = min (A, C) * D <= C * D <= A * B + C * D.

Then consider that the largest ci an edge. If it is selected, based on the above theory, the other side will be selected. If you check the other side had a ring to prove it is not a minimum spanning tree, is clearly illegal. Otherwise, we can calculate the answer at this time.
If it is not selected, in addition to the equivalent of seeking optimum value of this edge. This in turn recursively into a problem child.

But this is too slow. Better to turn, considering ci small to large enumeration.
At this time, if this edge were added, resulting in a ring, and the minimum spanning tree contradiction, this time ignoring the direct i th edge (class kruskal process).
Otherwise, this calculation point set of edges connected min {b}, max {a }. At this time, since the ci i is the maximum, so that direct access to max {ci, max {a} } to.

In order not to join with the optimum contrast value of the i-th side, we have to maintain a set point for each f, represents what before adding i-1 edges of the point set optimal answer yes.

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 300000;
struct edge{
    int u, v; ll w;
    edge(int _u=0, int _v=0, ll _w=0) : u(_u), v(_v), w(_w) {}
    friend bool operator < (edge a, edge b) {
        return a.w < b.w;
    }
}e[MAXN + 5];
int fa[MAXN + 5];
ll f[MAXN + 5], ma[MAXN + 5], mb[MAXN + 5];
int find(int x) {
    return fa[x] = (fa[x] == x ? x : find(fa[x]));
}
void unite(int x, int y, ll w) {
    int fx = find(x), fy = find(y);
    if( fx != fy ) {
        mb[fy] = min(mb[fy], mb[fx]);
        ma[fy] = max(ma[fy], ma[fx]);
        f[fy] = min(f[fx] + f[fy], max(ma[fy], w)*mb[fy]);
        fa[fx] = fy;
    }
}
int main() {
    int n, m; scanf("%d%d", &n, &m);
    for(int i=1;i<=n;i++) scanf("%lld%lld", &ma[i], &mb[i]);
    for(int i=1;i<=m;i++) scanf("%d%d%lld", &e[i].u, &e[i].v, &e[i].w);
    for(int i=1;i<=n;i++) fa[i] = i, f[i] = ma[i]*mb[i];
    sort(e + 1, e + m + 1);
    for(int i=1;i<=m;i++) unite(e[i].u, e[i].v, e[i].w);
    ll ans = 0;
    for(int i=1;i<=n;i++)
        if( find(i) == i ) ans += f[i];
    printf("%lld\n", ans);
}

@details@

I feel it is quite clever title, using a lot more properties, write code that is not very long.
(I never learned graph theory .jpg)

Guess you like

Origin www.cnblogs.com/Tiw-Air-OAO/p/11768046.html
Old