zoukankan      html  css  js  c++  java
  • noip 2015 运输计划 (lca+二分)

    /*
    95 最后一个点T了 qian lv ji qiong 了 
    没学过树剖 听chx听xzc说的神奇的方法  Orz
    首先求出每个计划的路径长度 这里写的倍增
    然后二分答案
    对于每个ans 统计>他的路径条数 tot 并维护最大差值 dec 
    并且对于每条不合法的路径维护每个点的经过次数
    然后枚举点 如果经过次数==tot说明每一条不合法的都经过他
    然后尝试把它建成虫洞 如果他对应边的权值>=dec 那么我们删掉它ans就合法了
    关键是统计每个点在非法路径中的经过次数 :
    维护sum数组 对于每个非法的路径起点a b LCA(a,b)==s sum[a]++ sum[b]++ sum[s]-=2
    这样网上更新的话 经过的点的sum值都变成1 祖先s的变成0 
    这样就实现了sum数组的维护 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #define maxn 300100
    using namespace std;
    int n,m,num,head[maxn],ans,inf;
    int fa[maxn][30],dep[maxn],dis[maxn],sum[maxn],edge[maxn];
    struct node
    {
        int u,v,t,pre;
    }e[maxn*2];
    struct Ans
    {
        int ai,bi,anc,di;
    }lca[maxn];
    int init()
    {
        int x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    void Add(int from,int to,int dis)
    {
        num++;
        e[num].u=from;
        e[num].v=to;
        e[num].t=dis;
        e[num].pre=head[from];
        head[from]=num;
    }
    void Dfs(int now,int from,int c,int Dis)
    {
        fa[now][0]=from;
        dep[now]=c;dis[now]=Dis;
        for(int i=head[now];i;i=e[i].pre)
          if(e[i].v!=from)
            {
              edge[e[i].v]=i;
              Dfs(e[i].v,now,c+1,Dis+e[i].t);
            }
    }
    void Get_fa()
    {
        for(int j=1;j<=16;j++)
          for(int i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1];
    }
    int Get_same(int a,int t)
    {
        for(int i=0;i<16;i++)
         if(t&(1<<i)) a=fa[a][i];
        return a;
    }
    int LCA(int a,int b)
    {
        if(dep[a]<dep[b])swap(a,b);
        a=Get_same(a,dep[a]-dep[b]);
        if(a==b)return a;
        for(int i=16;i>=0;i--)
          if(fa[a][i]!=fa[b][i])
            {
              a=fa[a][i];
              b=fa[b][i];
            }
        return fa[a][0];
    }
    void Init()
    {
        n=init();m=init();
        int u,v,t;
        for(int i=1;i<=n-1;i++)
          {
              u=init();v=init();t=init();
              Add(u,v,t);Add(v,u,t);
          }
        Dfs(1,1,0,0);
        Get_fa();
        for(int i=1;i<=m;i++)
          {
              lca[i].ai=init();lca[i].bi=init();
              lca[i].anc=LCA(lca[i].ai,lca[i].bi);
              lca[i].di=dis[lca[i].ai]+dis[lca[i].bi]-2*dis[lca[i].anc];
              inf=max(inf,lca[i].di);
          }
    }
    void Up_sum(int now,int from)
    {
        for(int i=head[now];i;i=e[i].pre)
          if(e[i].v!=from)
            {
              Up_sum(e[i].v,now);
              sum[now]+=sum[e[i].v];
            }
    }
    int Judge(int x)
    {
        memset(sum,0,sizeof(sum));
        int tot=0,dec=0;
        for(int i=1;i<=m;i++)
          if(lca[i].di>x)//非法路径 
            {
              tot++;
              dec=max(dec,lca[i].di-x);//最长非法路径与ans差值 
              sum[lca[i].ai]++;
              sum[lca[i].bi]++;
              sum[lca[i].anc]-=2;
            }
        Up_sum(1,1);//更新sum数组 
        for(int i=1;i<=n;i++)
          if(tot==sum[i]&&e[edge[i]].t>=dec)//删掉edge[i]这条边之后答案合法了 
            return 1;
        return 0;
    }
    void Solve()//二分答案 
    {
        int l=0,r=inf;
        while(l<=r)
          {
              int mid=(l+r)/2;
              int tmp=Judge(mid);
              if(tmp==1)
                {
                    r=mid-1;
                    ans=mid;
              }
            else l=mid+1;
          }
    }
    void Printf()
    {
        printf("%d
    ",ans);
    }
    int main()
    {
        //freopen("transport.in","r",stdin);
        //freopen("transport.out","w",stdout);
        Init();
        Solve();
        Printf();
        return 0;
    }
  • 相关阅读:
    redis.conf
    redis 超全的操作
    Oracle数据库导入导出命令
    技巧总结
    C#把Object对象转换成JSON串
    vscode c++ 开发环境踩坑
    vscode python 开发环境+qgis开发
    算法设计与分析:贪心算法
    操作系统概念习题
    贪心算法:贪心选择性与优化子结构
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5559491.html
Copyright © 2011-2022 走看看