[2019.1.3]BZOJ4326 NOIP2015 运输计划

看到最大值最小,第一个想到二分答案。

那么我们需要改成虫洞的边必然被所有大于当前答案的路径覆盖,我们只要在这些边中找到一条时间最大的,看看删去以后能否使之前耗时最长的路径耗时小于等于答案就好了。

那么如何找到满足条件的边呢?

我们可以将每一条超出答案的路径上所有的边打上一个标记,(标记数量=超出答案的边的数量)的边即是满足条件的边。

但是暴力打标记就T了。

所以我们要树上差分。

然后就可以了。

洛谷卡常,卡了好几天过不去,直到某一个神仙(orz)换上了他的码风才过去(神仙的码风快我两倍以上orz)。

大致就是从

倍增LCA+vector存图+自己码风+无fread+O2=\(\color{blue}\texttt{TLE}\)

变成

树剖LCA+vector存图+自己码风+fread+无O2(开了就MLE不知为什么)=\(\color{blue}\texttt{TLE}\)

然后

树剖LCA+链式前向星存图+自己码风+fread+无O2(开了就全TLE不知为什么)=\(\color{blue}\texttt{TLE}\)

最后

树剖LCA+链式前向星存图+神仙码风+fread+无O2=\(\color{green}\texttt{AC}\)

提交记录

code:

神仙码风可读性差,还是放了自己的码风,AC代码在后面

(自己的码风可读性也不高嘛...)

#include<bits/stdc++.h>
using namespace std;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
struct edge{
    int t,w,nxt;
}e[600010];
struct Path{
    int a,b,lca,len;
}p[300010];
int n,m,u,v,t,beg[300010],cnt,lg,vis[300010],f[300010],tp[300010],sz[300010],sum[300010],dep[300010],l,r,mid,siz,s[300010],mxe,mxl;
void add(int x,int y,int val){
    e[++cnt].t=y;
    e[cnt].w=val;
    e[cnt].nxt=beg[x];
    beg[x]=cnt;
}
int Dfs(int x){
    vis[x]=1;
    sz[x]=1;
    for(int i=beg[x];i;i=e[i].nxt)if(!vis[e[i].t])dep[e[i].t]=dep[x]+1,sum[e[i].t]=sum[x]+e[i].w,sz[x]+=Dfs(e[i].t);else f[x]=e[i].t;
    return sz[x];
}
int Dfs2(int x){
    int mxs=0,d=0;
    for(int i=beg[x];i;i=e[i].nxt)if(e[i].t!=f[x]&&sz[e[i].t]>mxs)mxs=sz[e[i].t],d=e[i].t;
    if(d)tp[d]=tp[x],Dfs2(d);
    for(int i=beg[x];i;i=e[i].nxt)if(e[i].t!=f[x]&&e[i].t!=d)tp[e[i].t]=e[i].t,Dfs2(e[i].t);
}
int LCA(int x,int y){
    while(tp[x]!=tp[y]){
        if(dep[tp[x]]<dep[tp[y]])swap(x,y);
        x=f[tp[x]];
    }
    if(dep[y]<dep[x])return y;
    return x;
}
int dfs(int x){
    int tot=s[x],tfe=0;
    for(int i=beg[x];i;i=e[i].nxt)if(e[i].t!=f[x])tot+=dfs(e[i].t);else tfe=e[i].w;
    if(tot==siz)mxe=max(mxe,tfe);
    return tot;
}
bool check(int x){
    mxe=mxl=siz=0;
    memset(s,0,sizeof(s));
    for(int i=1;i<=m;i++)if(p[i].len>x)s[p[i].a]++,s[p[i].b]++,s[p[i].lca]-=2,mxl=max(mxl,p[i].len),siz++;
    dfs(1);
    return mxl-mxe<=x;
}
void scan(int &x){
    x=0;
    char c=getchar();
    while('0'>c||c>'9')c=getchar();
    while('0'<=c&&c<='9')x=x*10+c-'0',c=getchar();
}
int main(){
    scan(n),scan(m);
    for(int i=1;i<n;i++)scan(u),scan(v),scan(t),add(u,v,t),add(v,u,t);
    dep[1]=1;
    Dfs(1);
    tp[1]=1;
    Dfs2(1);
    for(int i=1;i<=m;i++)scan(p[i].a),scan(p[i].b),p[i].lca=LCA(p[i].a,p[i].b),p[i].len=sum[p[i].a]+sum[p[i].b]-2*sum[p[i].lca],r=max(r,p[i].len);
    while(l<r){
        mid=(l+r)/2;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    printf("%d",l);
    return 0;
}

神仙码风:

code:

#include<bits/stdc++.h>
using namespace std;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#define add(x,y,val) (e[++cnt].t=y,e[cnt].w=val,e[cnt].nxt=beg[x],beg[x]=cnt)
#define swap(x,y) (x^=y^=x^=y)
char buf[1<<21],*p1=buf,*p2=buf;
struct edge{
    int t,w,nxt;
}e[600010];
struct Path{
    int a,b,lca,len;
}p[300010];
int n,m,u,v,t,beg[300010],cnt,lg,vis[300010],f[300010],tp[300010],sz[300010],sum[300010],dep[300010],l,r,mid,siz,s[300010],mxe,mxl;
int Dfs(int x){
    vis[x]=1,sz[x]=1;
    for(register int i=beg[x];i;i=e[i].nxt) vis[e[i].t]?(f[x]=e[i].t):(dep[e[i].t]=dep[x]+1,sum[e[i].t]=sum[x]+e[i].w,sz[x]+=Dfs(e[i].t));
    return sz[x];
}
void Dfs2(int x){
    register int i,mxs=0,d=0;
    for(i=beg[x];i;i=e[i].nxt) e[i].t^f[x]&&sz[e[i].t]>mxs&&(mxs=sz[e[i].t],d=e[i].t);
    for(d&&(tp[d]=tp[x],Dfs2(d),0),i=beg[x];i;i=e[i].nxt) e[i].t^f[x]&&e[i].t^d&&(tp[e[i].t]=e[i].t,Dfs2(e[i].t),0);
}
inline int LCA(int x,int y){
    while(tp[x]^tp[y]) dep[tp[x]]<dep[tp[y]]&&swap(x,y),x=f[tp[x]];
    return dep[y]<dep[x]?y:x;
}
int dfs(int x){
    register int i,tot=s[x],tfe=0;
    for(i=beg[x];i;i=e[i].nxt) e[i].t^f[x]?tot+=dfs(e[i].t):tfe=e[i].w;
    return tot==siz&&(mxe<tfe)&&(mxe=tfe),tot;
}
inline bool check(int x){
    mxe=mxl=siz=0,memset(s,0,sizeof(s));
    for(register int i=1;i<=m;++i) p[i].len>x&&(++s[p[i].a],++s[p[i].b],s[p[i].lca]-=2,mxl=max(mxl,p[i].len),++siz);
    return dfs(1),mxl-mxe<=x;
}
inline void scan(int &x){
    x=0;
    register char c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))x=(x<<3)+(x<<1)+(c&15),c=getchar();
}
int main(){
    register int i;
    for(scan(n),scan(m),i=1;i<n;++i)scan(u),scan(v),scan(t),add(u,v,t),add(v,u,t);
    for(dep[1]=1,Dfs(1),tp[1]=1,Dfs2(1),i=1;i<=m;i++)scan(p[i].a),scan(p[i].b),p[i].lca=LCA(p[i].a,p[i].b),p[i].len=sum[p[i].a]+sum[p[i].b]-(sum[p[i].lca]<<1),r<p[i].len&&(r=p[i].len);
    while(l<r)check(mid=l+r>>1)?r=mid:l=mid+1;
    return printf("%d",l),0;
}
posted @ 2019-03-17 17:59  xryjr233  阅读(127)  评论(0编辑  收藏  举报