zoukankan      html  css  js  c++  java
  • 基础算法(二分,贪心):NOIP 2012 疫情控制

    题目大意

      给出一棵n个节点的树,根是1,要在除根节点以外的点建立检查点,使得从每条根到叶子的路径上都至少存在一个检查点。检查点由军队来建立。初始军队的位置是给定的,移动军队走一条边需要花费这条边的权值的时间。现在要求一个方案,移动军队到某个最佳位置,使得总用时最少。

    【数据范围】
    保证军队不会驻扎在首都。
    对于20%的数据,2≤ n≤ 10;
    对于40%的数据,2 ≤n≤50,0<w <105
    对于60%的数据,2 ≤ n≤1000,0<w <106
    对于80%的数据,2 ≤ n≤10,000;
    对于100%的数据,2≤m≤n≤50,000,0<w <109

      这道题目没有想象的那样难,先是二分答案,再用倍增,接着树形dp,然后是贪心地分配判断是否合法。

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <vector>
      6 using namespace std;
      7 typedef long long LL;
      8 const LL INF=1ll<<50;
      9 const int N=50010,D=17;
     10 int cnt,fir[N],nxt[N*2];
     11 int to[N*2];LL val[N*2];
     12 LL dis[D][N],fa[D][N];
     13 void addedge(register int a,register int b,LL w){
     14   nxt[++cnt]=fir[a];
     15   fir[a]=cnt;
     16   val[cnt]=w;
     17   to[cnt]=b;
     18 }
     19 int n,m,dep[N];
     20 void Prepare(){
     21   for(register int k=1;k<=16;k++)
     22     for(register int i=1;i<=n;i++){
     23       fa[k][i]=fa[k-1][fa[k-1][i]];
     24       dis[k][i]=dis[k-1][i]+dis[k-1][fa[k-1][i]];
     25     }
     26 }
     27 void DFS(register int x){
     28   for(register int i=fir[x];i;i=nxt[i])
     29     if(to[i]!=fa[0][x]){
     30       fa[0][to[i]]=x;
     31       dep[to[i]]=dep[x]+1;
     32       dis[0][to[i]]=val[i];
     33       DFS(to[i]);
     34     }
     35 }
     36 int dp[N],st[N];
     37 vector<LL>v[N];
     38 void DP(register int x){
     39   if(dep[x]>1)
     40     dp[x]=v[x].size();
     41   else dp[x]=0;
     42   bool tmp=true,flag=false;
     43   for(register int i=fir[x];i;i=nxt[i])
     44     if(to[i]!=fa[0][x]){
     45       DP(to[i]);
     46       tmp&=dp[to[i]];
     47       flag=true;
     48     }
     49   dp[x]|=tmp&flag;
     50 }
     51 int ca,cb,p[N];
     52 LL a[N],b[N],c[N];
     53 bool Check(LL mid){
     54   for(register int i=1;i<=n;i++)
     55     v[i].clear();
     56   for(register int i=1;i<=m;i++){
     57     LL tmp=mid;register int x=st[i];
     58     for(register int k=16;k>=0;k--)
     59       if(dis[k][x]<=tmp){
     60           if(fa[k][x]<=1)continue;
     61     tmp-=dis[k][x];
     62     x=fa[k][x];
     63       }
     64     v[x].push_back(tmp);
     65   }
     66   DP(1);ca=cb=0;
     67   for(register int i=fir[1],y;i;i=nxt[i]){
     68     register int sz=v[y=to[i]].size(),z=0;
     69     if(!dp[y])b[++cb]=val[i],z=cb;
     70     for(register int j=0;j<sz;j++){
     71       a[++ca]=v[y][j]-val[i];
     72       c[ca]=z;
     73     }
     74   }
     75   memset(p,0,sizeof(p));
     76   for(register int i=1;i<=ca;i++){
     77     if(!p[c[i]])p[c[i]]=i;
     78     else if(a[p[c[i]]]>a[i])
     79       p[c[i]]=i;
     80   }
     81   for(register int i=1;i<=cb;i++)
     82     if(p[i]&&b[i]>a[p[i]]){
     83       b[i]=a[p[i]]=INF;
     84     }
     85   sort(a+1,a+ca+1);while(a[ca]==INF)ca--;
     86   sort(b+1,b+cb+1);while(b[cb]==INF)cb--;
     87   for(register int i=1,j=1;i<=ca;i++){
     88     if(a[i]>=b[j])j++;
     89     if(j>cb)return true;
     90   }
     91   return false;
     92 }
     93 
     94 
     95 LL l,r,mid,w;
     96 int main(){
     97   freopen("blockade.in","r",stdin);
     98   freopen("blockade.out","w",stdout);
     99   scanf("%d",&n);
    100   for(register int i=1,a,b;i<n;i++){
    101     scanf("%d%d%lld",&a,&b,&w);
    102     addedge(a,b,w);
    103     addedge(b,a,w);
    104   }DFS(1);Prepare();
    105   scanf("%d",&m);
    106   for(register int i=1;i<=m;i++)
    107     scanf("%d",&st[i]);
    108   l=0;r=INF;
    109   while(l<=r){
    110     mid=(l+r)>>1;
    111     if(Check(mid))r=mid-1;
    112     else l=mid+1;
    113   }
    114   if(l>INF)l=-1;
    115   printf("%lld
    ",l);
    116   return 0;
    117 }
  • 相关阅读:
    大规模机器学习
    机器学习之推荐系统
    SVM实现邮件分类
    机器学习之异常检测
    降维算法学习
    手写数字识别实现
    动态规划训练之十七
    概率期望训练之三
    数据结构训练之四
    绵阳东辰国际test201910.25
  • 原文地址:https://www.cnblogs.com/TenderRun/p/6072924.html
Copyright © 2011-2022 走看看