JZOJ 3104【NOIP2012提高组】疫情控制
来源:互联网 发布:数易生日23:00后计算法 编辑:程序博客网 时间:2024/05/22 00:25
Description
给出一棵n个节点的树,根是1,要在除根节点以外的点建立检查点,使得从每条根到叶子的路径上都至少存在一个检查点。检查点由军队来建立。初始军队的位置是给定的,移动军队走一条边需要花费这条边的权值的时间。现在要求一个方案,移动军队到某个最佳位置,使得总用时最少。
Analysis
控制疫情的时间取决于时间最长的军队,而题目要求总用时最少,最大值最小就可以二分了。
为了方便叙述,我们称根节点的子节点为目标点。
首先二分答案
然后,在
所以可以倍增走。这样就是
然后军队分两种情况:能走到根的和走不到根的。
对于走不到根的,把每个军队可以走到的最高点都标个号。如果一个节点所有子节点都标了号或该节点自身标了号,就说明是可以控制的节点。然后如果有目标点被控制了,就不用理它了。
剩下就交给走到根的军队。
对于这些,算出他们剩余的时间,求出他们所属的目标点。
然后求出所有未控制的目标点到根的长度,与军队匹配。注意匹配时有些特殊情况需要额外考虑。
Code
#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,b,a) for(int i=b;i>=a;i--)using namespace std;typedef long long ll;const int N=50005;int n,m,tot,to[N*2],next[N*2],last[N];int numx,numy,a[N],b[N],c[N],deep[N],f[N][16];ll wei[N*2],g[N][16];struct node{ int v; ll w;}x[N],y[N];bool bz[N];bool cmp(node a,node b){return a.w<b.w;}void link(int u,int v,ll w){ to[++tot]=v; wei[tot]=w; next[tot]=last[u]; last[u]=tot;}void dfs1(int v,int from,ll k,int dep,int S){ b[v]=S,deep[v]=dep; for(int i=last[v];i;i=next[i]) { int u=to[i]; if(u==from) continue; f[u][0]=v,g[u][0]=wei[i]; dfs1(u,v,k+wei[i],dep+1,S); }}int DA(int v,int S,ll lim){ fd(i,int(log2(deep[v])),0) if(deep[f[v][i]] && lim>=g[v][i]) lim-=g[v][i],v=f[v][i]; if(v==1) x[++numx].v=S,x[numx].w=lim; return v;}void dfs2(int v,int from){ bool p=1,q=0; for(int i=last[v];i;i=next[i]) { int u=to[i]; if(u==from) continue; q=1; dfs2(u,v); if(!bz[u]) p=0; } if(p && q) bz[v]=1;}bool check(ll lim){ memset(bz,0,sizeof(bz)); numx=0; fo(i,1,m) { int v=a[i]; int u=DA(v,b[v],lim); bz[u]=1; } dfs2(1,1); fo(i,1,numx) { int v=x[i].v; int S=b[v]; if(!bz[S] && x[i].w<c[S]) { bz[S]=1; x[i].v=0,x[i].w=-1; } } numy=0; for(int i=last[1];i;i=next[i]) { int u=to[i]; if(!bz[u]) y[++numy].v=u,y[numy].w=wei[i]; } sort(x+1,x+numx+1,cmp); sort(y+1,y+numy+1,cmp); int i=1,j=1; while(j<=numy) { if(bz[y[j].v]) { j++; continue; } if(i>numx) break; if(x[i].w>=y[j].w) i++,j++; else bz[x[i++].v]=1; } if(j>numy) return 1; return 0;}int main(){ int u,v; ll w,l=0,r=0,mid; scanf("%d",&n); fo(i,1,n-1) { scanf("%d %d %lld",&u,&v,&w); r+=w; link(u,v,w),link(v,u,w); } deep[1]=1; for(int i=last[1];i;i=next[i]) { u=to[i]; c[u]=wei[i]; f[u][0]=1,g[u][0]=wei[i]; dfs1(u,1,wei[i],2,u); } fo(j,1,int(log2(n))) fo(i,1,n) { f[i][j]=f[f[i][j-1]][j-1]; g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1]; } scanf("%d",&m); fo(i,1,m) scanf("%d",&a[i]); while(l<r) { mid=(l+r)>>1; if(check(mid)) r=mid; else l=mid+1; } printf("%lld",l); return 0;}
0 0
- JZOJ 3104【NOIP2012提高组】疫情控制
- 【NOIP2012提高组】疫情控制
- 【NOIP2012提高组】疫情控制
- NOIP2012提高组Day2 第3题 疫情控制
- 【思维】NOIP2012疫情控制
- NOIP2012 疫情控制
- noip2012疫情控制
- codevs1218: [NOIP2012]疫情控制
- 【NOIP2012】Day2T3 疫情控制
- NOIP2012 疫情控制
- [NOIP2012]疫情控制
- noip2012:疫情控制
- NOIp2012疫情控制
- 【NOIP2012】疫情控制
- [NOIP2012]疫情控制
- 【NOIP2012】疫情控制
- [noip2012]疫情控制
- NOIP2012复赛提高组day2(A:同余方程 B:借教室 C:疫情控制)
- 面向网络的PHP开发第26章
- UITableView API大百科
- Virtex6 PCIe 超简版基础概念学习(二)
- CocoaPods 的安装和使用
- 移除数组中的重复元素
- JZOJ 3104【NOIP2012提高组】疫情控制
- scope颜色修改
- Openfire4.0.2源码部署到Eclipse
- sudo apt-get update出现错误
- js部分基础知识
- java的守护线程与非守护线程
- App审核不通过的一般情况总结
- mysql使用kill命令解决死锁问题,杀死某条正在执行的sql语句
- sqoop.Sqoop: Got exception running Sqoop: java.lang.IllegalArgumentException: There is no column fou