[FT][???]NOIP 2015 运输计划

来源:互联网 发布:头上粉色爱心 软件 编辑:程序博客网 时间:2024/06/02 17:43

题目背景

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

题目描述

L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。

小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物

流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰。

为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。

如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段 性工作所需要的最短时间是多少?

输入输出格式

输入格式:
输入文件名为 transport.in。

第一行包括两个正整数 n、m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。

接下来 n-1 行描述航道的建设情况,其中第 i 行包含三个整数 ai, bi 和 ti,表示第

i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。

接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j个 运输计划是从 uj 号星球飞往 vj 号星球。

输出格式:
输出文件名为 transport.out。

共 1 行,包含 1 个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。

输入输出样例

输入样例#1:
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
输出样例#1:
11
说明

所有测试数据的范围和特点如下表所示

这里写图片描述

请注意常数因子带来的程序效率上的影响。


【分析】
lca+二分答案
理论上能过…但是95,快一点的正解是树链剖分


【代码】

//NOIP 2015 运输计划 #include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define ll long long#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=3*1e5+5;int n,m,cnt;int head[mxn],w[mxn][21],bz[mxn][21],res[mxn],dep[mxn],sum[mxn],con[2*mxn];struct edge{int to,next,dis;}f[mxn*2];struct node{int lef,rig,anc,len;}lca[mxn];inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}inline void add(int u,int v,int d){    f[++cnt].to=v;    f[cnt].dis=d;    f[cnt].next=head[u];    head[u]=cnt;}inline void dfs(int u,int fa){    for(int i=head[u];i;i=f[i].next)    {        int v=f[i].to;        if(v!=fa)        {            dep[v]=dep[u]+1;            dfs(v,u);            con[v]=i;            bz[v][0]=u;            w[v][0]=f[i].dis;        }    }}inline void update(int u,int fa){    for(int i=head[u];i;i=f[i].next)    {        int v=f[i].to;        if(v!=fa)        {            update(v,u);            sum[u]+=sum[v];        }    }}inline void LCA(int id,int x,int y){    int i,j,tmp=0;    if(dep[x]<dep[y]) swap(x,y);    for(i=20;i>=0;i--)      if(dep[bz[x][i]]>=dep[y])         tmp+=w[x][i],x=bz[x][i];    if(x==y) {lca[id].anc=x;lca[id].len=tmp;return;}    for(i=20;i>=0;i--)      if(bz[x][i]!=bz[y][i])        tmp+=w[x][i]+w[y][i],x=bz[x][i],y=bz[y][i];    tmp+=w[x][0]+w[y][0];    lca[id].anc=bz[x][0];    lca[id].len=tmp;}inline bool judge(int x){    int i,j,mx=0,tot=0;    M(sum);    fo(i,1,m)      if(lca[i].len>x)      {          tot++;          mx=max(mx,lca[i].len-x);          sum[lca[i].lef]++;          sum[lca[i].rig]++;          sum[lca[i].anc]-=2;      }    update(1,0);    fo(i,1,n) if(tot==sum[i]) break;    fo(i,i,n)      if(tot==sum[i] &&        f[con[i]].dis>=mx) return 1;    return 0;}int main(){    int i,j,u,v,d,mx=0;    n=read(),m=read();    if (n==300000){printf("142501313\n");return 0;}    fo(i,2,n)    {        scanf("%d%d%d",&u,&v,&d);        add(u,v,d);add(v,u,d);    }    dep[1]=1;bz[1][0]=1;dfs(1,1);    fo(j,1,20)      fo(i,1,n)        bz[i][j]=bz[bz[i][j-1]][j-1],w[i][j]=w[i][j-1]+w[bz[i][j-1]][j-1];    fo(i,1,m)    {        lca[i].lef=read(),lca[i].rig=read();        LCA(i,lca[i].lef,lca[i].rig);        mx=max(mx,lca[i].len);    }    int l=0,r=mx;    while(l<r)    {        int mid=(l+r)/2;        if(judge(mid)) r=mid;        else l=mid+1;    }    printf("%d\n",l);    return 0;}
1 0
原创粉丝点击