http://www.lydsy.com/JudgeOnline/problem.php?id=4326

题目描述

公元2044年,人类进入了宇宙纪元。

【BZOJ 4326】【NOIP2015】运输计划国有【BZOJ 4326】【NOIP2015】运输计划个星球,还有【BZOJ 4326】【NOIP2015】运输计划条双向航道,每条航道建立在两个星球之间,这【BZOJ 4326】【NOIP2015】运输计划条航道连通了【BZOJ 4326】【NOIP2015】运输计划国的所有星球。

【BZOJ 4326】【NOIP2015】运输计划掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从【BZOJ 4326】【NOIP2015】运输计划号星球沿最快的宇航路径飞行到【BZOJ 4326】【NOIP2015】运输计划号星球去。显然,飞船驶过一条航道是需要时间的,对于航道【BZOJ 4326】【NOIP2015】运输计划,任意飞船驶过它所花费的时间为【BZOJ 4326】【NOIP2015】运输计划,并且任意两艘飞船之间不会产生任何干扰。

为了鼓励科技创新,【BZOJ 4326】【NOIP2015】运输计划国国王同意小【BZOJ 4326】【NOIP2015】运输计划的物流公司参与【BZOJ 4326】【NOIP2015】运输计划国的航道建设,即允许小【BZOJ 4326】【NOIP2015】运输计划把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。在虫洞的建设完成前小【BZOJ 4326】【NOIP2015】运输计划的物流公司就预接了【BZOJ 4326】【NOIP2015】运输计划个运输计划。在虫洞建设完成后,这【BZOJ 4326】【NOIP2015】运输计划个运输计划会同时开始,所有飞船一起出发。当这【BZOJ 4326】【NOIP2015】运输计划个运输计划都完成时,小【BZOJ 4326】【NOIP2015】运输计划的物流公司的阶段性工作就完成了。如果小【BZOJ 4326】【NOIP2015】运输计划可以自由选择将哪一条航道改造成虫洞,试求出小【BZOJ 4326】【NOIP2015】运输计划的物流公司完成阶段性工作所需要的最短时间是多少?

输入格式

第一行包括两个正整数【BZOJ 4326】【NOIP2015】运输计划,表示【BZOJ 4326】【NOIP2015】运输计划国中星球的数量及小【BZOJ 4326】【NOIP2015】运输计划公司预接的运输计划的数量,星球从1到【BZOJ 4326】【NOIP2015】运输计划编号。接下来【BZOJ 4326】【NOIP2015】运输计划行描述航道的建设情况,其中第【BZOJ 4326】【NOIP2015】运输计划行包含三个整数 【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划,表示第【BZOJ 4326】【NOIP2015】运输计划条双向航道修建在【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划两个星球之间,任意飞船驶过它所花费的时间为【BZOJ 4326】【NOIP2015】运输计划。数据保证 。接下来【BZOJ 4326】【NOIP2015】运输计划行描述运输计划的情况,其中第【BZOJ 4326】【NOIP2015】运输计划行包含两个正整数【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划,表示第【BZOJ 4326】【NOIP2015】运输计划个运输计划是从【BZOJ 4326】【NOIP2015】运输计划号星球飞往【BZOJ 4326】【NOIP2015】运输计划号星球。

输出格式

输出文件只包含一个整数,表示小【BZOJ 4326】【NOIP2015】运输计划的物流公司完成阶段性工作所需要的最短时间。

输入样例

6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5

输出样例

11

数据范围

【BZOJ 4326】【NOIP2015】运输计划

 

题解

【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划二分【BZOJ 4326】【NOIP2015】运输计划路径交

利用 【BZOJ 4326】【NOIP2015】运输计划 求出每条路径的长度,二分答案 【BZOJ 4326】【NOIP2015】运输计划,对于所有路径 【BZOJ 4326】【NOIP2015】运输计划 的路径都至少需要删掉一条边,最优方案一定是删去这些路径交的最长边,即 【BZOJ 4326】【NOIP2015】运输计划 的路径都经过的一条最长边。

考虑如何求出路径交:【BZOJ 4326】【NOIP2015】运输计划 表示点 【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划 这一条边经过的路径数,对于一条从 【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划 的路径,将【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划【BZOJ 4326】【NOIP2015】运输计划,向上求和即可。

 

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#define depth 21
#define N 300005
using namespace std;

int n,m,tot,ans;
int anc[N][22],a[N],b[N],d[N],lca[N],last[N],dep[N],fa[N],sum[N],v[N],dis[N];
stack<int> s;
struct hh
{
    int to,next,w;
}e[N<<1];
int read()
{
    int ret=0;char c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c)){ret=(ret<<1)+(ret<<3)+c-'0';c=getchar();}
    return ret;
}
void add(int fr,int to,int w)
{
    e[++tot].to=to;
    e[tot].w=w;
    e[tot].next=last[fr];
    last[fr]=tot;
}
void bfs(int root)
{
    int i,j,now;
    s.push(root);
    dep[root]=1;
    for(i=0;i<=depth;i++)
        anc[root][i]=root;
    while(!s.empty())
    {
        now=s.top();s.pop();
        if(now!=root)
            for(i=1;i<=depth;i++)
                anc[now][i]=anc[anc[now][i-1]][i-1];
        for(i=last[now];i;i=e[i].next)
            if(!dep[e[i].to])
            {
                dep[e[i].to]=dep[now]+1;
                anc[e[i].to][0]=now;
                fa[e[i].to]=now; v[e[i].to]=e[i].w;
                dis[e[i].to]=dis[now]+e[i].w;
                s.push(e[i].to);
            }
    }
}
void swim(int &x,int h)
{
    int i;
    for(i=0;h;i++)
    {
        if(h&1) x=anc[x][i];
        h/=2;
    }
}
int get_lca(int x,int y)
{
    int i;
    if(dep[x]>dep[y]) swap(x,y);
    if(dep[x]!=dep[y]) swim(y,dep[y]-dep[x]);
    if(x==y) return x;
    while(true)
    {
        for(i=0;anc[x][i]!=anc[y][i];i++);
        if(i==0) return anc[x][0];
        i--;x=anc[x][i];y=anc[y][i];
    }
    
}
void work(int now)
{
    int i,j;
    for(i=last[now];i;i=e[i].next)
        if(e[i].to!=fa[now])
        {
            work(e[i].to);
            sum[now]+=sum[e[i].to];
        }
}
bool check(int lim)
{
    int i,j,cnt=0,t=0;
    for(i=1;i<=n;i++) sum[i]=0;
    for(i=1;i<=m;i++)
        if(d[i]>lim)
        {
            cnt++;
            t=max(t,d[i]-lim);
            sum[a[i]]++;sum[b[i]]++;
            sum[lca[i]]-=2;
        }
    work(1);
    for(i=1;i<=n;i++)
        if(sum[i]==cnt&&v[i]>=t) return true;
    return false;
    
}

int main()
{
    int i,j,u,v,w,l,r,mid;
    n=read();m=read();
    for(i=1;i<=n-1;i++)
    {
        u=read();v=read();w=read();
        add(u,v,w);add(v,u,w);
    }
    bfs(1);
    for(i=1;i<=m;i++)
    {
        a[i]=read();b[i]=read();
        lca[i]=get_lca(a[i],b[i]);
        d[i]=dis[a[i]]+dis[b[i]]-(dis[lca[i]]<<1);
    }
    l=0,r=d[1];
    for(i=2;i<=m;i++) r=max(r,d[i]);
    ans=99999999;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid)) ans=min(ans,mid),r=mid-1;
        else l=mid+1;
    }
    printf("%d",ans);
    return 0;
}

相关文章:

  • 2021-08-21
  • 2021-11-14
  • 2022-12-23
  • 2021-08-19
  • 2021-12-13
猜你喜欢
  • 2021-07-12
  • 2021-11-27
  • 2022-01-18
  • 2021-10-29
  • 2021-10-03
  • 2021-07-30
相关资源
相似解决方案