@loj - 2339 @ "WC2018" channel


@desription@

11328 years, C country's scientists have developed a high-speed transmission channels, from one end of the residents can be sent to the other end of the channel in a very short period of time, these channels are bi-directional.

The only drawback is that this delivery channel requires a lot of maintenance and repair. After programming, the new president States decided C M such channels in the city, the city of M, n transmission stations is established and the 3 × (n-1) conveying path section, the transmission channels are divided into three groups, each group It includes (n-1) channels.

When any of a set of channels running, a resident can transfer station to any other station through the set of channels transmitted from any. That is, all stations will be transmitting communication channel. Three channels 1, 2 run in turn in the order, the cycle is repeated. At any one time, and have only one set of transmission channels may be used. Formally, the i-th days, and only the first ((i-1) mod3 + 1) group channel operation.

C Access Globe country famous scientist conducting an experiment social survey: survey of user information transfer channel between the two transfer stations. Access Globe's plan is this:
select two transfer stations a, b
of the first day, he started from a, use of this group of channels running along the shortest path to reach the b and survey information on all channels through which users
the next day, he set out from b, the use of this group of channels running along the shortest path to reach a, and the investigation on all channels through which the user information
on the third day, he started from a, use of this group of channels running along the shortest path to b, and investigation on all channels through which the user information
Access Globe know the number of users each transmission line at run time. He hoped to find one pair of a, b, so that all of the channels through the entire course of the experiment and the maximum number of users. Access Globe wish to participate in CCF NOI 2018 winter camp of you to help him solve this simple little question. If you manage to solve this problem, Access Globe will send you a small gift - 100 points!

Input format
of the input file comprises a first line positive integer n, the number of the transmitting station, transmission station number from 1 to n;
the second to n-th line of the input file, each line contains three numbers u, v, w indicating there is a first set of channels connecting u, v passages, when the number of users which runs w person;
of (n + 1) to the second input file (2n-1) rows, each row comprising a number 3 u, v, w, represents the second set of channels has a connector u, v passages, when the number of users which runs w person;
of 2n to the second (3n-2) line of the input file, each row containing three the number of u, v, w, a third set of channels has a connector u, v channel, the number of users which runtime w person.

Output format
output file of 1 line, contains an integer representing the maximum number of users and.

A sample
INPUT
. 5
. 1 2 2
. 1 0. 3
. 1. 1. 4
. 4. 5. 7
. 1 2 0
2. 3. 1
2. 4. 1
2. 5. 3
. 1. 5 2
2. 3. 8
. 3. 4. 5
. 4. 5. 1

output
27

explanation
a feasible solution is to choose a = 2, b = 5, such as the number of users, and (3) + (5 + 8 + 1) + (2 + 1 + 7) = 27.

And agreed limits
for all data, 2≤n≤10 ^ 5,0≤w≤10 ^ 12.

@solution@

[Sticky topic is uoj because the mathematical formula loj bad stick]

Over the past year is not afraid of what became the template title / entry title bar. . . But then on what technology should be it black. . .
It should be said, possibly because of side partition is not the slightest popularity. . . Why, obviouslyI was here firstAnd dotted rule is similar algorithms. . .

Well into the topic. We make the first tree is t1, the second tree is t2, the third tree is t3.
Briefly Title: seeking one pair (u, v) such that t1.dis (u, v) + t2.dis (u, v) + t3.dis (u, v) maximum.
Briefly problem solution: t1 + t2 edge Partition + t3 maintenance virtual tree diameter.

T1 and then consider the reconstruction side partition, because the right side is not so good right point reconstruction.
In each layer, the current communication center side communication block into two blocks. We consider all paths through the (u, V), denoted F [u] represents the distance of the center side end edge from the center point u, denoted center side length val.
For the two communicating in different blocks u, v have t1.dis (u, v) = f [u] + val + f [v]. Val can be found in the u and v are independent, so we only need to claim the f [u] + f [v ] + t2.dis (u, v) + maximum t3.dis (u, v) of.

For each layer, at t2, the construction of this layer block corresponding to the virtual communication tree. Enumeration lca u and v is p, the problem of converting to f [u] + f [v ] + t2.dep [u] + t2.dep [v] - 2 * t2.dep [p] + t3. dis (u, v).
It can be found t2.dep [p] and u, v independent actually required (f [u] + t2.dep [ u]) + (f [v] + t2.dep [v]) + t3.dis ( u, v) maximum.

We can point t3 in for each i to build a new point i ', i' i connected to f [i] + t2.dep [i ] side, simply requires t3.dis (u ', v') . Do not even need this edge on the actual implementation, this is only for the convenience of thinking.
One conclusion: the set of vertices to two S, T, S, in a selected endpoint, another endpoint in the selected T path obtained maximum diameter will end diameter end in S and T which two at the distance between the generation.
Maintenance can then be used by class methods dp in time t2, dfs point within subtree i t1, corresponding to two blocks communication t3 in diameter respectively, and maintain the optimum value can be the answer. Maintenance diameter can also use the above conclusion.

t1 side partition, side partition for each layer run in a virtual tree t2, this place is the bottleneck of the time complexity of O (nlog ^ 2 n).
Incidentally, there is a method seeking lca O (nlog n) pretreated O (1) query (into rmq). This question needs to solve a lot of places because of the distance so use this method to be faster.

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
#define fi first
#define se second
typedef long long ll;
typedef pair<int, int> pii;
const int MAXN = 200000;
int lg[MAXN + 5];
struct Graph{
    struct edge{
        bool tag;
        int to; ll dis;
        edge *nxt, *rev;
    }edges[2*MAXN + 5], *adj[MAXN + 5], *ecnt;
    int dfn[2*MAXN + 5], fir[MAXN + 5], dep[MAXN + 5], dcnt;
    int st[20][MAXN + 5]; ll dis[2*MAXN + 5];
    Graph() {dcnt = 0, ecnt = &edges[0];}
    void addedge(int u, int v, ll w) {
    //  printf("! %d %d %lld\n", u, v, w);
        edge *p = (++ecnt), *q = (++ecnt);
        p->to = v, p->dis = w, p->tag = false;
        p->nxt = adj[u], adj[u] = p;
        q->to = u, q->dis = w, q->tag = false;
        q->nxt = adj[v], adj[v] = q;
        q->rev = p, p->rev = q;
    }
    void dfs(int x, int f) {
        dep[x] = dep[f] + 1;
        dfn[++dcnt] = x, fir[x] = dcnt;
        for(edge *p=adj[x];p;p=p->nxt) {
            if( p->to == f ) continue;
            dis[p->to] = dis[x] + p->dis;
            dfs(p->to, x);
            dfn[++dcnt] = x;
        }
    }
    void get_st() {
        for(int i=1;i<=dcnt;i++)
            st[0][i] = dfn[i];
        for(int j=1;j<20;j++) {
            int t = (1<<(j-1));
            for(int i=1;i+t<=dcnt;i++)
                st[j][i] = (dep[st[j-1][i]] <= dep[st[j-1][i+t]]) ? st[j-1][i] : st[j-1][i+t];
        }
    }
    void build() {dfs(1, 0), get_st();}
    int lca(int u, int v) {
        if( fir[u] > fir[v] ) swap(u, v);
        int k = lg[fir[v] - fir[u] + 1], l = (1<<k);
        return (dep[st[k][fir[u]]] <= dep[st[k][fir[v]-l+1]]) ? st[k][fir[u]] : st[k][fir[v]-l+1];
    }
    ll dist(int u, int v) {return dis[u] + dis[v] - 2*dis[lca(u, v)];}
}G1, G2, G3, G4;
int n, m;
void rebuild(const Graph &G1, Graph &G2, int x, int f) {
    int lst = -1;
    for(Graph::edge *p=G1.adj[x];p;p=p->nxt) {
        if( p->to == f ) continue;
        rebuild(G1, G2, p->to, x);
        if( lst == -1 ) {
            G2.addedge(x, p->to, p->dis);
            lst = x;
        }
        else {
            int s = (++m);
            G2.addedge(lst, s, 0);
            G2.addedge(s, p->to, p->dis);
            lst = s;
        }
    }
}
void init() {
    for(int i=2;i<=MAXN;i++)
        lg[i] = lg[i>>1] + 1;
}
int tid[MAXN + 5], dcnt = 0;
void get_tid(Graph &G, int x, int f) {
    tid[x] = (++dcnt);
    for(Graph::edge *&p=G.adj[x];p;p=p->nxt)
        if( p->to != f ) get_tid(G, p->to, x);
}
int siz[MAXN + 5];
bool comp(Graph::edge *a, Graph::edge *b, int tot) {
    if( a == NULL ) return false;
    if( b == NULL ) return true;
    return max(siz[a->to], tot-siz[a->to]) < max(siz[b->to], tot-siz[b->to]);
}
Graph::edge *get_mid_edge(const Graph &G, int x, int f, int tot) {
    Graph::edge *ret = NULL; siz[x] = 1;
    for(Graph::edge *p=G.adj[x];p;p=p->nxt) {
        if( p->to == f || p->tag ) continue;
        Graph::edge *tmp = get_mid_edge(G, p->to, x, tot);
        siz[x] += siz[p->to];
        if( tmp && comp(tmp, ret, tot) )
            ret = tmp;
        if( comp(p, ret, tot) )
            ret = p;
    }
    return ret;
}
bool cmp(int a, int b) {
    return tid[a] < tid[b];
}
int arr[MAXN + 5], stk[MAXN + 5], type[MAXN + 5], acnt = 0, tp = 0, root;
ll dis[MAXN + 5];
void dfs(const Graph &G, int x, int f, int t, ll d) {
    if( x <= n )
        acnt++, arr[acnt] = x, type[x] = t, dis[x] = d + G2.dis[x];
    for(Graph::edge *p=G.adj[x];p;p=p->nxt) {
        if( p->to == f || p->tag ) continue;
        dfs(G, p->to, x, t, d + p->dis);
    }
}
void insert(int x) {
    if( !tp ) {
        stk[++tp] = x;
        return ;
    }
    int l = G2.lca(stk[tp], x);
    if( l == stk[tp] ) {
        stk[++tp] = x;
        return ;
    }
    else {
        while( true ) {
            int x = stk[tp--];
            if( tp && tid[stk[tp]] >= tid[l] ) {
                G2.addedge(stk[tp], x, G2.dist(stk[tp], x));
                if( stk[tp] == l ) break;
            }
            else {
                stk[++tp] = l;
                G2.addedge(l, x, G2.dist(l, x));
                break;
            }
        }
        stk[++tp] = x;
    }
}
void build_vtree(const Graph &G, Graph::edge *m) {
    G2.ecnt = &G2.edges[0];
    acnt = 0, dfs(G, m->to, 0, -1, 0), dfs(G, m->rev->to, 0, 1, 0);
    sort(arr + 1, arr + acnt + 1, cmp);
    for(int i=1;i<=acnt;i++)
        insert(arr[i]);
    root = stk[1];
    while( tp ) {
        int x = stk[tp--];
        if( tp ) G2.addedge(x, stk[tp], G2.dist(x, stk[tp]));
    }
}
ll func(const int &a, const int &b, const int &c) {
    return dis[a] + dis[b] - 2*G2.dis[c] + G3.dist(a, b);
}
void update2(ll &ans, const pii &a, const pii &b, const int &x) {
    ans = max(ans, func(a.fi, b.fi, x)), ans = max(ans, func(a.fi, b.se, x));
    ans = max(ans, func(a.se, b.fi, x)), ans = max(ans, func(a.se, b.se, x));
}
void update4(pii &a, const int &b, const int &x) {
    ll p = func(a.fi, b, x), q = func(a.se, b, x), r = func(a.fi, a.se, x);
    if( p >= q && p >= r ) a.se = b;
    else if( q >= p && q >= r ) a.fi = b;
}
void update1(pair<pii, pii>&a, const pair<pii, pii>&b, ll &ans, const int &x) {
    if( a.fi.fi ) {
        if( b.se.fi ) update2(ans, a.fi, b.se, x);
        if( b.fi.fi ) update4(a.fi, b.fi.fi, x), update4(a.fi, b.fi.se, x);
    }
    else a.fi = b.fi;
    if( a.se.fi ) {
        if( b.fi.fi ) update2(ans, a.se, b.fi, x);
        if( b.se.fi ) update4(a.se, b.se.fi, x), update4(a.se, b.se.se, x);
    }
    else a.se = b.se;
}
pair<pii, pii>dfs1(int x, int f, ll &ans) {
    pair<pii, pii>ret = make_pair(make_pair(0, 0), make_pair(0, 0));
    if( type[x] ) {
        if( type[x] == 1 ) ret.first = make_pair(x, x);
        if( type[x] == -1 ) ret.second = make_pair(x, x);
    }
    for(Graph::edge *&p=G2.adj[x];p;p=p->nxt) {
        if( p->to == f ) continue;
        pair<pii, pii>tmp = dfs1(p->to, x, ans);
        update1(ret, tmp, ans, x);
    }
    return ret;
}
ll divide(const Graph &G, int x, int tot) {
    Graph::edge *m = get_mid_edge(G, x, 0, tot);
    if( m == NULL ) return 0;
    m->tag = m->rev->tag = true;
    build_vtree(G, m);
    ll ans = 0;
    dfs1(root, 0, ans); ans += m->dis;
    for(int i=1;i<=acnt;i++)
        type[arr[i]] = 0;
    return max(ans, max(divide(G, m->to, siz[m->to]), divide(G, m->rev->to, tot-siz[m->to])));
}
int main() {
    init();
    scanf("%d", &n);
    for(int i=1;i<n;i++) {
        int u, v; ll w;
        scanf("%d%d%lld", &u, &v, &w);
        G1.addedge(u, v, w);
    }
    for(int i=1;i<n;i++) {
        int u, v; ll w;
        scanf("%d%d%lld", &u, &v, &w);
        G2.addedge(u, v, w);
    }
    for(int i=1;i<n;i++) {
        int u, v; ll w;
        scanf("%d%d%lld", &u, &v, &w);
        G3.addedge(u, v, w);
    }
    m = n, rebuild(G1, G4, 1, 0);
    G2.build(), G3.build(), G4.build();
    get_tid(G2, 1, 0);
    printf("%lld\n", divide(G4, 1, m));
}

@details@

Although long to write but actually not difficult, it is easy to write accordance with the idea to write out.
The basic nor how debug.

Guess you like

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