疫情控制
来源:互联网 发布:软件著作权申请要求 编辑:程序博客网 时间:2024/05/02 00:57
传送门
思路:贪心+二分。
首先我们的军队肯定是越往上越好。
那么我们二分一个时间,让军队在这个时间内尽可能的向上走。然后跑DFS去看看是否封锁了所有的边境城镇。
如果一个子树上根本没有军队怎么办。那么只能从其他子树调过来了。
将可以到根节点并且时间有富裕的军队所剩余的时间排序。
然后把没有军队的子树的时间也排序,找一个时间最相近的去到那颗子树上是最优的。
预处理倍增距离和祖节点
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#define ll long longusing namespace std;const ll maxm=50105; ll head[maxm],net[2*maxm],to[2*maxm],cost[2*maxm];ll cnt,jd[maxm],f[maxm][19];ll dis[maxm][19],mindis[maxm];//dis表示i向上2^j层的时间,f表示i向上2^j层的地方 bool vis[maxm],use[maxm];ll have[maxm],tot1,tot2;ll n;struct node{ ll id; ll rest;};node a[maxm],b[maxm];bool comp(node x,node y){ return x.rest>y.rest;}void add(ll x,ll y,ll c){ cnt++; to[cnt]=y; cost[cnt]=c; net[cnt]=head[x]; head[x]=cnt;}void dfs(ll x,ll fat,ll Dis){ dis[x][0]=Dis,f[x][0]=fat; for(ll i=1;i<=17;i++) { f[x][i]=f[f[x][i-1]][i-1]; dis[x][i]=dis[x][i-1]+dis[f[x][i-1]][i-1]; } for(ll i=head[x];i;i=net[i]) if(to[i]!=fat) dfs(to[i],x,cost[i]);}bool ok(ll x,ll fat){ bool f1=1,f2=0; if(vis[x]) return 1; for(ll i=head[x];i;i=net[i]) if(to[i]!=fat) { f2=1; if(ok(to[i],x)==0) { f1=0; if(x==1) b[++tot2].rest=cost[i],b[tot2].id=to[i]; else return 0; } } if(!f2) return 0; return f1;}bool check(ll mid,ll q){ //return 0; //printf("%d\n",q); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(vis,0,sizeof(a)); memset(use,0,sizeof(use)); memset(have,0,sizeof(have)); tot1=0,tot2=0; for(ll i=1;i<=q;i++) { ll x=jd[i],sum=0; //printf("hhhhh\n"); for(ll j=17;j>=0;j--) if(f[x][j]>1&&sum+dis[x][j]<=mid) sum+=dis[x][j],x=f[x][j]; if(f[x][0]==1&&dis[x][0]+sum<=mid) { a[++tot1].rest=mid-dis[x][0]-sum,a[tot1].id=i; if(!have[x]||a[tot1].rest<mindis[x]) mindis[x]=a[tot1].rest,have[x]=i; } else vis[x]=1; } if(ok(1,0)) return 1; sort(a+1,a+tot1+1,comp); sort(b+1,b+tot2+1,comp); ll now=1; use[0]=1; for(ll i=1;i<=tot2;i++) { //return 0; if(use[have[b[i].id]]==0) { use[have[b[i].id]]=1; continue; } while(now<=tot1&&(use[a[now].id]||a[now].rest<b[i].rest))++now; if(now>tot1) return 0; use[a[now].id]=1; //printf("%lld %lld %lld\n",mid,b[i].id,b[i].rest); } //puts("2333"); return 1;}int main(){ ll q; scanf("%lld",&n); for(ll i=1,x,y,c;i<n;i++) scanf("%lld%lld%lld",&x,&y,&c),add(x,y,c),add(y,x,c); scanf("%lld",&q); //printf("%d\n",q); for(ll i=1;i<=q;i++) scanf("%lld",&jd[i]); dfs(1,0,0); //printf("%lld %lld\n",dis[2][0],dis[4][1]); ll l=0,r=1e9+100; while(l<=r) { ll mid=(l+r)/2; if(check(mid,q)) r=mid-1; else l=mid+1; } if(r==1e9+100) l=-1; printf("%lld",l);}
阅读全文
1 0
- 疫情控制
- 疫情控制
- 疫情控制
- 【思维】NOIP2012疫情控制
- NOIP2012 疫情控制
- JZOJ 3104.疫情控制
- P1084 疫情控制
- noip2012疫情控制
- P1084 疫情控制
- NOIP 2012 疫情控制
- 洛谷 P1084 疫情控制
- codevs1218: [NOIP2012]疫情控制
- NOIP2012DAY2T3【疫情控制】
- 【NOIP2012】Day2T3 疫情控制
- 洛谷 P1084 疫情控制
- NOIP2012 疫情控制
- [NOIP2012]疫情控制
- 【jzoj3104】【疫情控制】
- 订单系统
- SQLserver2008错误5120的解决方法
- struts2自定义类型转换器
- netty源码分析(十)ChannelPipeline创建时机与高级拦截过滤器模式的运用
- 数字和字符串的互相转化
- 疫情控制
- Linux下的tar压缩解压缩命令详解
- 订餐系统
- ApkToolPlus 是一个可视化的跨平台 apk 分析工具,使用 java 语言开发的一个桌面应用。
- 编程作业50页第5题 使用for循环语句计算8+88+888.....前10项之和
- 模仿Struts2流程写QuickStart入门程序
- 打印发生错误的文件、函数、行号
- 安卓项目快速开发框架, MVP + Retrofit + RxJava,Activity 和 Fragment 结合 MVP 模式的完整封装,大大减少代码量
- 第五天-python数据类型-2