luogu1084 [NOIp2012]疫情控制 (二分答案+倍增+dfs序)
先二分出一个时间,把每个军队倍增往上跳到不能再跳
然后如果它能到1号点,就记下来它跳到1号点后剩余的时间;如果不能,就让它就地扎根,记一记它覆盖了哪些叶节点(我在这里用了dfs序+差分,其实直接dfs就行..)
然后对于那些叶节点没有被覆盖完全的(父亲为1号点的)子树,肯定需要一些已经到1号点的军队来走过去
如果它离1距离越远,肯定就希望用剩余时间越多的军队来走,除非是有一个剩余时间更少的军队本来就在这个子树里
看一看能不能符合要求的就行了
然而有很多要注意的地方:
0.一个军队只能用一次......(开始读错题 还在想为什么会有-1的情况)
1.只需要覆盖叶节点就行了,也就是说,统计这个子树有没有完全被覆盖的时候,不能统计到非叶节点
2.即使有军队本来在这个子树里,我也有可能不选这个军队来到这个子树里,因为它的剩余时间可能非常大
3.有可能到1号点的军队数不足覆盖掉那些没被覆盖的子树,这时候也是-1
4.每次judge要清零...
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=5e4+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 struct Edge{ 16 int b,ne;ll l; 17 }eg[maxn*2]; 18 int egh[maxn],ect; 19 int N,M,p[maxn]; 20 int dfn[maxn][2],tot,fa[maxn][20]; 21 int bel[maxn],cnt[maxn],tmp[maxn],tmp2[maxn]; 22 int mim[maxn],id[maxn]; 23 bool flag[maxn],islef[maxn]; 24 ll dis[maxn][20],rest[maxn]; 25 26 inline void adeg(int a,int b,ll l){ 27 eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect; 28 } 29 30 void dfs(int x){ 31 dfn[x][0]=++tot;id[tot]=x; 32 for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++){ 33 fa[x][i+1]=fa[fa[x][i]][i]; 34 dis[x][i+1]=dis[x][i]+dis[fa[x][i]][i]; 35 }islef[x]=1; 36 for(int i=egh[x];i;i=eg[i].ne){ 37 int b=eg[i].b; 38 if(b==fa[x][0]) continue; 39 fa[b][0]=x;dis[b][0]=eg[i].l; 40 if(x==1) bel[b]=b; 41 else bel[b]=bel[x]; 42 dfs(b); 43 islef[x]=0; 44 } 45 dfn[x][1]=tot; 46 } 47 48 int getfe(int x,ll &lim){ 49 for(int i=17;i>=0;i--){ 50 if(fa[x][i]&&dis[x][i]<=lim) lim-=dis[x][i],x=fa[x][i]; 51 } 52 return x; 53 } 54 55 inline bool cmp(int a,int b){return rest[a]>rest[b];} 56 inline bool cmp2(int a,int b){return dis[a][0]>dis[b][0];} 57 58 inline bool judge(ll m){ 59 // printf("!!%lld:\n",m); 60 int n,i,j; 61 CLR(cnt,0); 62 for(i=1,j=0;i<=M;i++){ 63 rest[i]=m; 64 int x=getfe(p[i],rest[i]); 65 // printf("%d %d %lld\n",p[i],x,rest[i]); 66 if(x==1) tmp[++j]=i; 67 else{ 68 cnt[dfn[x][0]]++; 69 cnt[dfn[x][1]+1]--; 70 } 71 } 72 n=j;sort(tmp+1,tmp+n+1,cmp); 73 CLR(flag,1); 74 for(i=2,j=0;i<=N;i++){ 75 j+=cnt[i]; 76 if(j==0&&islef[id[i]]) flag[bel[id[i]]]=0; 77 } 78 CLR(mim,0); 79 for(i=n;i;i--){ 80 if((!flag[bel[p[tmp[i]]]])&&(!mim[bel[p[tmp[i]]]])){ 81 mim[bel[p[tmp[i]]]]=i; 82 } 83 } 84 for(i=2,j=0;i<=N;i++){ 85 if(fa[i][0]!=1||flag[i]) continue; 86 tmp2[++j]=i; 87 }m=j; 88 sort(tmp2+1,tmp2+m+1,cmp2); 89 if(n<m) return 0; 90 for(i=1,j=1;i<=n&&j<=m;i++){ 91 if(!tmp[i]) continue; 92 if(tmp[mim[tmp2[j]]]){ 93 tmp[mim[tmp2[j]]]=0; 94 i--; 95 }else{ 96 if(rest[tmp[i]]<dis[tmp2[j]][0]) return 0; 97 tmp[i]=0; 98 }j++; 99 } 100 return j>m; 101 } 102 103 int main(){ 104 // freopen("testdata (1).in","r",stdin); 105 int i,j,k; 106 N=rd(); 107 for(i=1;i<N;i++){ 108 int a=rd(),b=rd(),c=rd(); 109 adeg(a,b,c);adeg(b,a,c); 110 }dfs(1); 111 M=rd(); 112 for(i=1;i<=M;i++) p[i]=rd(); 113 ll l=0,r=1e15,ans=1e15+1; 114 while(l<=r){ 115 ll m=l+r>>1; 116 if(judge(m)) ans=m,r=m-1; 117 else l=m+1; 118 } 119 if(ans==1e15+1) printf("-1\n"); 120 else printf("%lld\n",ans); 121 return 0; 122 }