• 洛谷P2680 运输计划


    传送门

    二分所求的答案w,找出所有长度大于w的路径,用差分标记到树上。dfs一遍整棵树,找出所有标记在树上的路径的最长公共边,如果最长的一条路径减去这条边小于等于w,则w是满足题意的答案之一。

    预处理每条路径的长度和两端点的lca。

    复杂度n*log(最长路径),注意常数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=300010,M=300010;
    int n,m,ans,num,maxx,sum;
    int ver[2*N],Next[2*N],head[N],edge[2*N],tot;
    int tag[N];
    struct node{
        int x,y,lon,lca;
    }s[M];
    int read(){
        char ch=getchar();
        int val=0;
        for(;(ch<'0')||(ch>'9');ch=getchar());
        for(;(ch>='0')&&(ch<='9');val=val*10+ch-'0',ch=getchar());
        return val;
    }
    void add(int x,int y,int z){
        ver[++tot]=y;
        Next[tot]=head[x];
        head[x]=tot;
        edge[tot]=z;
    }
    int dep[N],st[N][21],dis[N][21];
    void dfs(int x,int fa){
        for(int i=1;i<=19;i++){
            st[x][i]=st[st[x][i-1]][i-1];
            dis[x][i]=dis[st[x][i-1]][i-1]+dis[x][i-1];
            if(!st[x][i])break;
        }
        for(int i=head[x];i;i=Next[i]){
            int y=ver[i];
            if(y==fa)continue;
            dep[y]=dep[x]+1;
            st[y][0]=x;
            dis[y][0]=edge[i];
            dfs(y,x);
        }
    }
    int get(int x,int y){
        if(dep[x]<dep[y])swap(x,y);
        for(int i=19;i>=0;i--){
            if(st[x][i]&&dep[st[x][i]]>=dep[y]){
                sum+=dis[x][i];
                x=st[x][i];
            }
        }
        if(x==y)return x;
        for(int i=19;i>=0;i--){
            if(st[x][i]!=st[y][i]){
                sum+=dis[x][i]+dis[y][i];
                x=st[x][i],y=st[y][i];
            }
        }
        sum+=dis[x][0]+dis[y][0];
        return st[x][0];
    }
    bool cmp(node x,node y){
        return x.lon<y.lon;
    }
    int dfs1(int x,int fa,int edg){
        int val=tag[x];
        for(int i=head[x];i;i=Next[i]){
            int y=ver[i];
            if(y==fa)continue;
            val+=dfs1(y,x,edge[i]);
        }
        if(val==num)maxx=max(maxx,edg);
        return val;
    }
    int check(int x){
        memset(tag,0,sizeof(tag));
        maxx=num=0;
        for(int i=m;i>=1;i--){
            if(s[i].lon<=x)break;
            tag[s[i].x]++,tag[s[i].y]++;
            tag[s[i].lca]-=2;
            num++;
        }
        if(!num)return 1;
        dfs1(1,0,0);
        return s[m].lon-maxx<=x;
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1,x,y,z;i<n;i++){
            x=read(),y=read(),z=read();
            add(x,y,z),add(y,x,z);
        }
        dfs(1,0);
        for(int i=1;i<=m;i++){
            s[i].x=read(),s[i].y=read();
            sum=0;
            s[i].lca=get(s[i].x,s[i].y);
            s[i].lon=sum;
        }
        sort(s+1,s+m+1,cmp);
        int l=0,r=s[m].lon;
        while(l<=r){
            int mid=(l+r)/2;
            if(check(mid)){
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    搭建一个Flv视频播放服务器
    nginx 搭建http协议拖动播放 FLV 视频播放服务器
    轻轻松松干掉flash右键菜单方法
    在Eclipse中配置tomcat7.0
    js中cookie的使用详细分析
    windows 版Tomcat 7.0的配置
    FMS服务器录制权限的开放NetStream.Record.NoAccess错误解决方法
    WCF入门(四)——会话与实例
    WCF selfhost测试
    WCF 消息队列通信
  • 原文地址:https://www.cnblogs.com/chloris/p/11860958.html
Copyright © 2020-2023  润新知