BZOJ3459 : Bomb

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

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

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

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

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

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

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

如此建图,点数和边数均为$O(n\log 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;
}

  

时间: 2024-10-10 05:04:47

BZOJ3459 : Bomb的相关文章

CSAPP 3e: Bomb lab (secret_phase)

这是秘密关卡,需要通过主动调用secret_phase函数才能触发,可以通过call secret 或者jump *0x地址来调用. 贴出函数:(fun7函数部分没有注释,后边续上了手写的图来解析这个函数了) 0000000000401204 <fun7>: 401204: 48 83 ec 08 sub $0x8,%rsp 401208: 48 85 ff test %rdi,%rdi 40120b: 74 2b je 401238 <fun7+0x34>;如果%rdi==0,r

CSAPP 3e: Bomb lab (phase_6)

这一关很复杂,需要非常耐心.如果感觉容易在循环中绕晕,可以参考一下我最后附上的画图分析法2333,小把戏,不过挺有用的. 先看函数phase_6: 00000000004010f4 <phase_6>: 4010f4: 41 56 push %r14 4010f6: 41 55 push %r13 4010f8: 41 54 push %r12 4010fa: 55 push %rbp 4010fb: 53 push %rbx 4010fc: 48 83 ec 50 sub $0x50,%rs

CSAPP 3e: Bomb lab (phase_5)

调出phase_5函数: 0000000000401062 <phase_5>: 401062: 53 push %rbx 401063: 48 83 ec 20 sub $0x20,%rsp 401067: 48 89 fb mov %rdi,%rbx 40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax ;此处搞不懂 401071: 00 00 401073: 48 89 44 24 18 mov %rax,0x18(%rsp) 401078: 31

HDU 3622 Bomb Game(二分+2-SAT)

Bomb Game Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5396    Accepted Submission(s): 1925 Problem Description Robbie is playing an interesting computer game. The game field is an unbounde

[HDU3555]Bomb

试题描述 The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power o

HDU 3555 —— Bomb

Bomb Problem Description The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "4

HDU 5653 Bomber Man wants to bomb an Array. DP

Bomber Man wants to bomb an Array. Problem Description Given an array and some positions where to plant the bombs, You have to print the Total Maximum Impact. Each Bomb has some left destruction capability L and some right destruction capability R wh

Bomb

Description The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the

hdu 3555 Bomb(数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题目大意:就是给你一个数n,判断从0到n有多少个数含有数字49...... 是不是觉得跟hdu2089很相似呀... 思路:跟hdu2089一样的,注意给出的数比较大,所以这儿用__int64  .... code: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm&