NOIP 2015

NOIP 2015

Day2

T3 transport plan

The meaning of problems: there is a \ (n-\) tree points, each side having a length, m is given path tree, you can select an edge, its length is changed to 0, this required the longest path m What is the shortest possible

\ (n-, m \ Le. 3 \ times10. 5 ^ \) , the side length of not more than \ (1000 \)

solution:

\ (1 \) binary answer, the length of the start intersection of overrun, if the intersection is 0, no solution, or selected from the longest side of the intersection

\ (2 \) tree intersection difference (-1 endpoint $ \ (, \) the LCA $ + 2)

Time complexity: \ (O (nlog ^ 2n) \)

\ (1 \) consider the intersection twenty-two path, then it must be found in both ends of the path of the \ (4 \) path in the deepest two months LCA LCA's (the title can do so, but also consider other issues \ (4 \) where like) th overlapped LCA.

\ (2 \) to do so found dichotomy is not very useful, you can put side descending order, followed by intersection, then the answer to enumerate, if the intersection is empty or the longest length is not enough, and on output answer. It can be \ (RMQ \) optimization request \ (the LCA \) .

Time complexity: \ (O (nlogn) \) heard by a number of methods may be magic (RMQ \) \ pretreatment to optimize \ (O (n-) \) , total time complexity reaches \ (O ( n) \)

For the first \ (O (nlog ^ 2n) \) solution, we have found may be pretreated directly LCA each pair, so that the time complexity will be reduced to \ (O (nlogn) \)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 300100
#define RE register 
int n, m;
int st[maxn], ed[maxn], len[maxn];
int fir[maxn], nxt[maxn * 2], vv[maxn * 2], edge[maxn * 2];
int tot = 0;
int read()
{
    int ret = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        ret = ret * 10 + ch - '0';
        ch = getchar();
    }
    return ret;
}
void add(int u, int v, int w)
{
    nxt[++tot] = fir[u];
    fir[u] = tot;
    vv[tot] = v;
    edge[tot] = w;
}
int dep[maxn], f[maxn][25], g[maxn][25];
void Deal_first(int u, int fa)
{
 //   printf("u = %d fa = %d\n", u, fa);
    dep[u] = dep[fa] + 1;
    for(RE int i = 0; i <= 19; i++)
    {
        f[u][i + 1] = f[f[u][i]][i];
        g[u][i + 1] = g[u][i] + g[f[u][i]][i];
    }
    for(RE int i = fir[u]; i; i = nxt[i])
    {
        int v = vv[i];
        if(v == fa) continue;
        f[v][0] = u;
        g[v][0] = edge[i];
        Deal_first(v, u);
    }
}
int LCA(int x, int y, int &dis)
{
    if(dep[x] < dep[y]) swap(x, y);
    for(RE int i = 20; i >= 0; i--)
    {
        if(dep[f[x][i]] >= dep[y])
        {
            dis += g[x][i];
    //        printf("g[x][i] = %d\n", g[x][i]);
            x = f[x][i];
        }
   //     printf("x = %d y = %d\n", x, y);
        if(x == y)
        {
            return x;
        }
    }
    for(RE int i = 20; i >= 0; i--)
    {
        if(f[x][i] != f[y][i])
        {
            dis += g[x][i];
            dis += g[y][i];
            x = f[x][i];
            y = f[y][i];
    //        printf("x = %d y = %d\n", x, y);
        }
    }
    dis += (g[x][0] + g[y][0]);
    return f[x][0];
}
int val[maxn], dp[maxn * 2], from[maxn], lc[maxn];
void dfs(int u, int fa)
{
    dp[from[u]] += val[u];
    for(RE int i = fir[u]; i; i = nxt[i])
    {
        int v = vv[i];
        if(v == fa) continue;
        from[v] = i;
        dfs(v, u);
        dp[from[u]] += dp[from[v]];
    }
}
int lenth;
int check(int x)
{
    memset(val, 0, sizeof(val));
    memset(dp, 0, sizeof(dp));
    int cnt = 0;
    for(RE int i = 1; i <= m; i++)
    {
        if(len[i] > x)
        {
            cnt++;
            int u = st[i], v = ed[i];
            int xx = 0;
            val[u] += 1; val[v] += 1;
            val[lc[i]] -= 2;
        }
   //     else break;
    }
    dfs(1, 0);
    int maxx = -1;
    for(RE int i = 1; i <= tot; i++)
    {
    //    printf("dp[%d] = %d ", i, dp[i]);
        if(dp[i] >= cnt)
        {
            maxx = max(maxx, edge[i]);
        }
    }
   // printf("\n");
   // printf("x = %d cnt = %d maxx = %d\n", x, cnt, maxx);
    if(!cnt) return 1;
    if(maxx == -1 || lenth - maxx > x) return 0;
    return 1;
}
bool cmp(int x, int y)
{
    return x > y;
}
int main()
{
    n = read(); m = read();
    for(RE int i = 1; i < n; i++)
    {
        int u, v, w;
        u = read(); v = read(); w = read();
        add(u, v, w); add(v, u, w);
    }
    for(RE int i = 1; i <= m; i++)
    {
        st[i] = read(); ed[i] = read();
    }
    Deal_first(1, 0);
    for(RE int i = 1; i <= m; i++)
    {
        int dis = 0;
        int fa = LCA(st[i], ed[i], dis);
        len[i] = dis; lenth = max(lenth, len[i]);
        lc[i] = fa;
    //    printf("u = %d v = %d fa = %d\n", st[i], ed[i], fa);
        //len[i] = dep[st[i]] + dep[ed[i]] - dep[LCA(st[i], ed[i])] * 2;
    }
   // sort(len + 1, len + m + 1, cmp);
   // for(int i = 1; i <= m; i++) printf("len[%d] = %d\n", i, len[i]);
    int l = 0, r = 3e8, ans = 0;
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(check(mid) == 1)
        {
            ans = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    printf("%d\n", ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/Akaina/p/11649446.html