zoukankan      html  css  js  c++  java
  • NOIP2015_提高组Day2_3_运输计划

    这题思路很简单;

    先对每个询问求距离,对距离由大到小排序,

    二分最小距离,验证是否可行,验证时用差分处理;

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<iomanip>
    #include<map>
    #include<set>
    #include<vector>
    #include<ctime>
    #include<cmath>
    #define LL long long 
    using namespace std;
    #define LL long long 
    #define up(i,j,n) for(int i=(j);(i)<=(n);(i)++)
    #define max(x,y) ((x)<(y)?(y):(x))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define FILE "1"
    #define pii pair<int,int>
    const int maxn=303000,inf=1000000000;
    int read(){
        int x=0;bool flag=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')flag=1;ch=getchar();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
        return flag?-x:x;
    }
    int n,m;
    struct node{
        int y,next,v;
    }e[maxn<<1];
    int linkk[maxn],len=0,fa[maxn],w[maxn],dep[maxn],top[maxn],siz[maxn],son[maxn],d[maxn];
    void insert(int x,int y,int v){
        e[++len].y=y;
        e[len].v=v;
        e[len].next=linkk[x];
        linkk[x]=len;
    }
    int q[maxn],tail=0,head=0;
    void dfs(int x){
        siz[x]=1;
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y==fa[x])continue;
            fa[e[i].y]=x;w[e[i].y]=e[i].v;dep[e[i].y]=dep[x]+1;
            dfs(e[i].y);
            siz[x]+=siz[e[i].y];
            if(siz[e[i].y]>siz[son[x]])son[x]=e[i].y;
        }
    }
    void dfs2(int x){
        if(son[x]){
            top[son[x]]=top[x];
            d[son[x]]=d[x]+w[son[x]];
            dfs2(son[x]);
        }
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y==fa[x]||e[i].y==son[x])continue;
            top[e[i].y]=e[i].y;
            d[e[i].y]=0;
            dfs2(e[i].y);
        }
    }
    pii lca(int x,int y){
        int u,v;
        int sum=0;
        while(x!=y){
            u=top[x],v=top[y];
            if(u==v)return make_pair((dep[x]>dep[y]?y:x),sum+abs(d[x]-d[y]));
            if(dep[u]>dep[v]){swap(x,y);swap(u,v);}
            sum+=d[y]+w[v];
            y=fa[v];
        }
        return make_pair(x,sum);
    }
    struct Node{
        int x,y,v,f;
        bool operator<(const Node &b)const{return v>b.v;}
    }a[maxn];
    int vis[maxn];
    int maxx=0,flag=0;
    void Dfs(int x){
        for(int i=linkk[x];i;i=e[i].next){
            if(e[i].y==fa[x])continue;
            Dfs(e[i].y);
            vis[x]+=vis[e[i].y];
        }
        if(vis[x]==flag)maxx=max(maxx,w[x]);
    }
    int work(int mid){
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=mid;i++)vis[a[i].x]++,vis[a[i].y]++,vis[a[i].f]-=2;//比较暴力的差分
        //可以利用树链剖分将树划分成线段,在上面做差分,常数要比这个小的多,实测结果是#20会超
        maxx=0;flag=mid;Dfs(1);
        return maxx;
    }
    void slove(){
        n=read();m=read();
        int x,y,v;
        up(i,2,n){
            x=read(),y=read(),v=read();
            insert(x,y,v);insert(y,x,v);
        }
        dfs(1);top[1]=1;
        dfs2(1);
        pii temp;
        up(i,1,m){
            a[i].x=read(),a[i].y=read();
            temp=lca(a[i].x,a[i].y);
            a[i].v=temp.second;a[i].f=temp.first;
        }
        sort(a+1,a+m+1);
        int left=1,right=m,mid,ans=inf;//也可以1-a[1].v这样枚举,加个记忆化就好;
        while(left<=right){
            mid=(left+right)>>1;
            int fee=a[1].v-work(mid);
            if(fee>a[mid+1].v)right=mid-1;
            else left=mid+1;
            ans=min(ans,max(fee,a[mid+1].v));
        }
        cout<<ans<<endl;
    }
    int main(){
        freopen(FILE".in","r",stdin);
        freopen(FILE".out","w",stdout);
        slove();
        return 0;
    }
    //如果window下评测注意加个开栈
    View Code
  • 相关阅读:
    2016.5.11_经典试题-回文算法【ABAP】
    shell基础知识
    python笔记2
    python笔记1
    vmware rdm
    网页中图片显示方向与实际图片方向不一致
    vue 弹性布局 实现长图垂直居上,短图垂直居中
    IE10 解决input file 同一文件不触发onchange事件
    04. pt-deadlock-logger
    03. pt-config-diff
  • 原文地址:https://www.cnblogs.com/chadinblog/p/5956232.html
Copyright © 2011-2022 走看看