洛谷P1084 疫情控制(NOIp2012)
来源:互联网 发布:吊顶软件下载 编辑:程序博客网 时间:2024/05/16 02:37
贪心 倍增 二分
题目传送门
细节很多。。。改了老半天
首先二分答案。然后不断把军队往根节点靠(倍增实现)。如果达不到根节点就直接打个标记。达到根节点后存下来,同时存剩余的路程。
DFS求出哪些1的子树是没有被拦的。首先考虑放从同一节点上来的军队。如果已经用过,贪心的按照距离远的配剩下的路程多的来放。
具体见注释
代码:
#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 50000using namespace std;typedef long long LL;struct edge{ int next,to; LL dis;}ed[MAXN*2+5];struct remain{ int x; LL v; }rem[MAXN+5],op[MAXN+5];//一个存军队,一个存子树int n,m,k;int h[MAXN+5],fa[MAXN+5][18],am[MAXN+5],flag[MAXN+5];LL dis[MAXN+5][18],rm[MAXN+5];bool f[MAXN+5],f1[MAXN+5];inline char readc(){//fread读优 static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); if (l==r) return EOF; return *l++;}inline LL _read(){ LL num=0; char ch=readc(); while (ch<'0'||ch>'9') ch=readc(); while (ch>='0'&&ch<='9') { num=num*10+ch-48; ch=readc(); } return num;}bool srch(int x){//DFS判断子树是否被拦 if (f[x]) return true; bool fl=false; for (int i=h[x];i;i=ed[i].next) if (ed[i].to!=fa[x][0]){//有一个没有被拦就算没有被拦 fl=true;//说明有子树 if (!srch(ed[i].to)) return false; } return fl;}bool cp(remain x,remain y){ return x.v>y.v; }bool pd(LL v){ int t=0,opn=0; memset(f1,false,sizeof(f1)); memset(f,false,sizeof(f)); memset(flag,0,sizeof(flag)); for (int i=1;i<=m;i++){ int x=am[i];LL tt=v; for (int j=17;j>=0;j--) if (dis[x][j]<=tt&&fa[x][j]>1) tt-=dis[x][j],x=fa[x][j]; if (tt<dis[x][0]||fa[x][0]!=1) f[x]=true;//如果到达不了根节点 else{ rem[++t].v=tt-dis[x][0]; rem[t].x=i; if (!flag[x]||rem[t].v<rm[x]) rm[x]=rem[t].v,flag[x]=i; } } for (int i=h[1];i;i=ed[i].next) if (!srch(ed[i].to)) op[++opn].v=ed[i].dis,op[opn].x=ed[i].to;//存起来 if (opn>t) return false; if (!opn) return true; sort(rem+1,rem+t+1,cp); sort(op+1,op+opn+1,cp); int nd=1; f1[0]=true; for (int i=1;i<=opn;i++){ if (!f1[flag[op[i].x]]) { f1[flag[op[i].x]]=true; continue; }//如果没有用过就用 while (nd<=t&&(f1[rem[nd].x]||rem[nd].v<op[i].v)) nd++; if (nd>t) return false; f1[rem[nd].x]=true; } return true;}void dfs(int x){ for (int i=h[x];i;i=ed[i].next) if (ed[i].to!=fa[x][0]){ int v=ed[i].to; fa[v][0]=x; dis[v][0]=ed[i].dis; dfs(v); }}void addedge(int x,int y,LL z){ ed[++k].next=h[x]; ed[k].to=y; ed[k].dis=z; h[x]=k;}void Make(){ for (int j=1;j<=17;j++) for (int i=1;i<=n;i++){ fa[i][j]=fa[fa[i][j-1]][j-1]; dis[i][j]=dis[i][j-1]+dis[fa[i][j-1]][j-1]; }}int main(){ n=_read(); for (int i=1;i<n;i++){ int u=_read(),v=_read(); LL d=_read(); addedge(u,v,d); addedge(v,u,d); } dfs(1); Make(); m=_read();//倍增预处理 for (int i=1;i<=m;i++) am[i]=_read(); LL l=0,r=500000,ans=-1;//二分答案 while (l<=r){ LL mid=(l+r)/2; if (pd(mid)) r=mid-1,ans=mid; else l=mid+1; } return printf("%lld\n",ans),0;}
阅读全文
1 0
- 洛谷P1084 疫情控制(NOIp2012)
- 洛谷 P1084 [NOIP2012 D2T3] 疫情控制
- 洛谷 P1084 疫情控制
- 洛谷 P1084 疫情控制
- 洛谷 P1084 疫情控制
- 疫情控制 洛谷p1084
- 洛谷P1084:疫情控制 (二分答案+倍增+贪心)
- 洛谷 P1084 疫情控制 (二分答案+倍增+贪心)
- P1084 疫情控制
- P1084 疫情控制
- 【NOIP2012】洛谷1084 疫情控制
- noip2012 疫情控制 (二分+倍增)
- [noip2012]疫情控制(二分+贪心)
- 【思维】NOIP2012疫情控制
- NOIP2012 疫情控制
- noip2012疫情控制
- codevs1218: [NOIP2012]疫情控制
- 【NOIP2012】Day2T3 疫情控制
- linux-系统延迟及定时机制
- 树莓派lnmp搭建
- JS设计模式之发布订阅模式
- 连续总结第二十一天
- LeetCode:60. Permutation Sequence
- 洛谷P1084 疫情控制(NOIp2012)
- typedef 定义数组类型用法
- 3、Oracle查询语句-from-字句
- bootstrap 大坑,大坑
- [Unity][PHOTON][UNET][SOCKET][Android]PC-Android建立聊天室ChatRoom交互通讯
- 征服number类型的input框
- springmvc常用注解标签详解
- day11c语言作业
- ResultSetMetaData和DatabaseMetaData