zoukankan      html  css  js  c++  java
  • BZOJ3459 : Bomb

    二分答案,转化成判定所有科学家能否在lim时间内走到安全的地方

    考虑网络流,对于每个非叶子节点,S向它连边,容量为该点科学家的人数

    对于每个叶子节点,向T连边,容量为该点的容量

    对于每个非叶子节点x,枚举它的所有祖先,对于一个祖先y,向y子树中所有与x距离不超过lim的点连边,容量为inf

    由于数据随机,所以树的高度期望为$O(log n)$

    可以先对于每个点把该点子树内所有叶子节点按距离排序,然后第i小的点向第i-1小的点连边

    每次查询时只要二分找到最大的满足条件的点然后向该点连边即可

    如此建图,点数和边数均为$O(nlog n)$

     

    #include<cstdio>
    #include<algorithm>
    const int N=10010,M=100010,inf=~0U>>2;
    int n,i,j,x,y,sum,a[N],b[N],f[N],w[N],G[N],v[N],nxt[N],ed,dis[N];
    int st[N],en[N],q[M],m,S,T,h[M],gap[M],maxflow,l,r=500000,mid,ans;
    int g[M],d[M],cur;
    struct E{int t,f,nxt;E(){}E(int _t,int _f,int _nxt){t=_t,f=_f,nxt=_nxt;}}e[1500000];
    inline bool cmp(int x,int y){return dis[x]<dis[y];}
    inline void addedge(int x,int y,int z){f[y]=x;w[y]=z;v[++ed]=y;nxt[ed]=G[x];G[x]=ed;}
    void dfs2(int x){
      if(!a[x])q[++m]=x;
      for(int i=G[x];i;i=nxt[i])dfs2(v[i]);
    }
    void dfs(int x){
      if(!a[x])return;
      for(int i=G[x];i;i=nxt[i])dis[v[i]]=dis[x]+w[v[i]],dfs(v[i]);
      st[x]=m+1;
      for(int i=G[x];i;i=nxt[i])dfs2(v[i]);
      en[x]=m;
      std::sort(q+st[x],q+m+1,cmp);
    }
    inline int min(int x,int y){return x<y?x:y;}
    inline void add(int s,int t,int f){
      e[++cur]=E(t,f,g[s]);g[s]=cur;
      e[++cur]=E(s,0,g[t]);g[t]=cur;
    }
    int sap(int v,int flow){
      if(v==T)return flow;
      int rec=0;
      for(int p=d[v];p;p=e[p].nxt)if(h[v]==h[e[p].t]+1&&e[p].f){
        int ret=sap(e[p].t,min(flow-rec,e[p].f));
        e[p].f-=ret;e[p^1].f+=ret;d[v]=p;
        if((rec+=ret)==flow)return flow;
      }
      if(!(--gap[h[v]]))h[S]=T;
      gap[++h[v]]++;d[v]=g[v];
      return rec;
    }
    bool check(int lim){
      for(cur=i=1;i<=T;i++)g[i]=d[i]=h[i]=gap[i]=0;
      for(i=n+1;i<=m;i++)add(i,q[i],inf);
      for(i=1;i<=n;i++)if(a[i]){
        add(S,i,b[i]);
        for(j=i;j;j=f[j])if(dis[q[st[j]]]<=lim+dis[j]*2-dis[i]){
          int l=st[j]+1,r=en[j],mid,t=st[j];
          while(l<=r)if(dis[q[mid=(l+r)>>1]]<=lim+dis[j]*2-dis[i])l=(t=mid)+1;else r=mid-1;
          add(i,t,inf);
        }
        for(j=st[i];j<en[i];j++)add(j+1,j,inf);
      }else add(i,T,b[i]);
      for(gap[maxflow=0]=T,i=1;i<=T;i++)d[i]=g[i];
      while(h[S]<T)maxflow+=sap(S,inf);
      return maxflow==sum;
    }
    int main(){
      scanf("%d",&n);
      for(i=1;i<=n;i++){
        for(scanf("%d",&a[i]),j=0;j<a[i];j++)scanf("%d%d",&x,&y),addedge(i,x,y);
        scanf("%d",&b[i]);
        if(a[i])sum+=b[i];
      }
      for(m=n,i=1;i<=n;i++)if(!f[i])dfs(i);
      S=m+1,T=S+1;
      while(l<=r)if(check(mid=(l+r)>>1))r=(ans=mid)-1;else l=mid+1;
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(88)-Excel导入和导出-主从表结构导出
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(89)-EF执行SQL语句与存储过程
    ASP.NET MVC5+EF6+EasyUI 后台管理系统-WebApi的用法与调试
    ASP.NET MVC5+EF6+EasyUI 仓库管理系统
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(91)-EF 连接 MySql
    样例功能截图
    Fastreport.net 如何在开发MVC应用程序时使用报表
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(90)-EF 扩展操作
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(87)-MVC Excel导入和导出
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(86)-日程管理-fullcalendar插件用法
  • 原文地址:https://www.cnblogs.com/clrs97/p/4715388.html
Copyright © 2011-2022 走看看