noip2015day2t3运输计划(二分+树上前缀和)

https://www.luogu.org/problem/show?pid=2680

题解::二分最大值,判断出所有大于最大值的路径的交,再判断能否达到最大值以下。求路径的交用树上前缀和,每次判断是O(n)的,总复杂度为O(nlogn);

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 300010
#define re register
using namespace std;
template<class T>inline void read(T &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9')f|=(ch=='-'),ch=getchar();
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=f?-x:x;
    return;
}
struct Node
{
    int u,v,sum,l;
     inline bool operator<(const Node&A)const{
    return A.sum<sum;
    }
}q[maxn];
int n,m,size[maxn],d[maxn],dis[maxn],cnt,pos[maxn],id,head[maxn],top[maxn],fa[maxn],dep[maxn],son[maxn];
struct node{int v,w,next;}e[600010];
inline void ins(int u,int v,int w){e[++cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt;}
void dfs1(int x)
{
    size[x]=1;
    for(re int p=head[x];p;p=e[p].next)
    {
        int v=e[p].v;
        if(fa[x]==v)continue;
        fa[v]=x;dep[v]=dep[x]+1;dis[v]=dis[x]+e[p].w;
        dfs1(v);
        size[x]+=size[v];
        if(size[v]>size[son[x]])son[x]=v;
    }
}
void dfs2(int x,int chain)
{
    top[x]=chain;pos[++id]=x;
    if(!son[x])return;
    dfs2(son[x],chain);
    for(re int p=head[x];p;p=e[p].next)
    if(e[p].v!=fa[x]&&e[p].v!=son[x])dfs2(e[p].v,e[p].v);
}
int lca(int x,int y)
{
    while(top[x]!=top[y])
    if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
    else y=fa[top[y]];
    return dep[x]<dep[y]?x:y;
}
bool check(int x)
{
    int t=0,Max=0;
    if(x>=q[1].sum)return true;
    memset(d,0,sizeof(d));
    for(re int i=1;i<=m;i++)
    {
        if(q[i].sum>x)
        {
            t++;
            d[q[i].u]++;d[q[i].v]++;d[q[i].l]-=2;
        }
        else break;
    }
    for(re int i=n;i>=1;i--)
    d[fa[pos[i]]]+=d[pos[i]];
    for(re int i=2;i<=n;i++)
    if(d[i]==t)Max=max(Max,dis[i]-dis[fa[i]]);
    if(q[1].sum-Max>x)return false;
    return true;
}
int main()
{
    int u,v,w;
    read(n);read(m);
    for(re int i=1;i<n;i++)
    {
        read(u);read(v);read(w);
        ins(u,v,w);ins(v,u,w);
    }
    dfs1(1);
    dfs2(1,1);
    for(re int i=1;i<=m;i++)
    {
        read(u);read(v);
        q[i].u=u;q[i].v=v;
        q[i].l=lca(u,v);
        q[i].sum=dis[u]+dis[v]-2*dis[q[i].l];
    }
    sort(q+1,q+1+m);
    int l=0,r=q[1].sum,mid;
    while(l<r)
    {
        mid=l+r>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    printf("%d
",r);
    return 0;
}
原文地址:https://www.cnblogs.com/jiangtao0508/p/7725581.html