luoguP1084 疫情控制(题解)(搜索+贪心)
Posted eternal风度
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP1084 疫情控制(题解)(搜索+贪心)相关的知识,希望对你有一定的参考价值。
#include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define il inline #define rg register #define ll long long #define N 60000 #define inf 2147483647 using namespace std; int n,m,hd[N],cnt,u,v,w; int c,idx[N]; int le,ri=500000; int dis[N][20],up[N][20]; int ok[N],use[N],vis[N]; struct S{ int res,idx; }ne[N],to[N]; struct T{ int nt,to,w; }edge[N<<1]; il void re(rg int &x); void add(rg int fm,rg int to,rg int w); void ST(rg int i,rg int fa); int check(rg int lim); int Dfs(rg int u,rg int fa); int Cmp(const S &x,const S &y); int main() { re(n); for(rg int i=1;i<n;++i) { re(u),re(v),re(w); add(u,v,w),add(v,u,w); if(u==1||v==1)c++; } re(m); if(m<c){cout<<-1;return 0;} for(rg int i=1;i<=m;++i) re(idx[i]); ST(1,0); for(rg int k=1;k<=19;++k) { for(rg int i=1;i<=n;++i) { up[i][k]=up[up[i][k-1]][k-1]; dis[i][k]=dis[up[i][k-1]][k-1]+dis[i][k-1]; } } while(le<ri) { rg int mid=((le+ri)>>1); if(check(mid))ri=mid; else le=mid+1; } cout<<le; return 0; } il void re(rg int &x) { rg int res=0;rg int w=1;char c=getchar(); while((c<‘0‘||c>‘9‘)&&c!=‘-‘)c=getchar(); if(c==‘-‘)w=-1,c=getchar(); while(c>=‘0‘&&c<=‘9‘)res=(res<<3)+(res<<1)+c-‘0‘,c=getchar(); x=w*res; } void add(rg int fm,rg int to,rg int w) { edge[++cnt].nt=hd[fm]; edge[cnt].to=to; edge[cnt].w=w; hd[fm]=cnt; } void ST(rg int i,rg int fa) { up[i][0]=fa; for(rg int k=hd[i];k;k=edge[k].nt) { rg int qw=edge[k].to; if(qw==fa)continue; dis[qw][0]=edge[k].w; ST(qw,i); } } int check(rg int lim){ memset(ok,0,sizeof(ok)); memset(use,0,sizeof(use)); memset(vis,0,sizeof(vis)); rg int cnt1=0,cnt2=0; rg int top=1; for(rg int i=1;i<=m;++i){ rg int res=lim,u=idx[i]; for(rg int k=19;k>=0;--k){ if(up[u][k]&&up[u][k]!=1&&res>=dis[u][k]) res-=dis[u][k],u=up[u][k]; } if(up[u][0]==1&&res>dis[u][0]) { to[++cnt1].res=res-dis[u][0]; to[cnt1].idx=u; } else ok[u]=1; } Dfs(1,0); for(rg int k=hd[1];k;k=edge[k].nt){ rg int qw=edge[k].to; if(!ok[qw]){ ne[++cnt2].res=dis[qw][0]; ne[cnt2].idx=qw; } } sort(to+1,to+cnt1+1,Cmp); sort(ne+1,ne+cnt2+1,Cmp); if(cnt1<cnt2)return 0; for(rg int i=1;i<=cnt1;++i) { if(!vis[to[i].idx]) { vis[to[i].idx]=1; continue; } while(vis[ne[top].idx])top++; if(to[i].res>=ne[top].res) { vis[ne[top].idx]=1,top++; continue; } if(top>cnt2)break; } while(vis[ne[top].idx])top++; if(top<=cnt2)return 0; return 1; } int Dfs(rg int u,rg int fa) { rg int temp=1,flag=0; for(rg int k=hd[u];k;k=edge[k].nt) { rg int qw=edge[k].to; if(qw==fa)continue; flag++,temp&=Dfs(qw,u); } if(!flag)temp=0; ok[u]=(ok[u]|temp); if(ok[u]&&up[u][0]==1) vis[u]=1; return ok[u]; } int Cmp(const S &x,const S &y){return x.res<y.res;}
以上是关于luoguP1084 疫情控制(题解)(搜索+贪心)的主要内容,如果未能解决你的问题,请参考以下文章
P1084 [NOIP2012 提高组] 疫情控制(倍增&贪心&二分)