[NOIP2012 day2] epidemic control

problem:

State-owned H n cities, cities with the n n-1 bidirectional path interconnected constitutes a tree, No. 1 is the capital city, is also the root of the tree.
H capital of the country broke out the dangers of a high infectious disease. Authorities in order to control the epidemic, to prevent spread of the epidemic (city leaf nodes represented) border city, decided to use military force to establish checkpoints in some cities, so that from the capital to the border city of each path has at least one checkpoint, border cities can also create a checkpoint. However, particular attention is that the capital can not be established checkpoints. Now, in some cities in the country H has stationed troops there, and a city could be stationed more troops.

An army can move between road links to the city and to establish checkpoints in any city other than the capital, and only a checkpoint in the city. An army after a road move from one city to another city needed time equal to the length of the road (unit: hour). Will the minimum number of hours required to control the epidemic. Note: Different forces can move simultaneously.

solution:

Before long you been doing this question, but I was still ruo, have not been playing for a long time, I do not know how to do, after a review of various trees and do question yesterday, I suddenly realize hammering change to change the tone of this question has finally been lost, super impressed. To write down my thoughts

 

First we look at the problem

Covering all leaf nodes within the shortest possible time required subject apparently dichotomous answers cover all leaf nodes clearly as possible in the shortest time to let the army hop doubled from the closer the better so if the root point jump less than the root then let him stop If there jump to the root node then recorded

Then look at DFS O (n) to find the root does not cover the leaf nodes of the son node record 

 

As greedy

The two arrays survive from small to large greedy at a minimum allocation of maximum minimum maximum allocation

If the current root node military presence son jumped to the root node is not covered then go to cover this point is clearly better

 

As for the distance doubling

For a long time I did not play too unfamiliar friends

$ DIS [i] [j] $ $ I $ node represents a jump from $ 2 ^ $ J a node through

Doubling the distance

ll go_up(ll s,int x)   
{   
    int k=ceil(log2(dep[x]));   
    for(int i=k;i>=0;i--)   
    {   
        if(f[x][i]&&s>=(dis[x][i])) {s-=dis[x][i];x=f[x][i];}   //注意顺序不要颠倒
    }   
    return x;   
}   

 

 

 

Well put code:

#include<stdio.h>
#include<bits/stdc++.h>   
using namespace std;   
#define maxnn 120000  
#define ll long long 
int n,m;   
int las[maxnn],nex[maxnn],en[maxnn],le[maxnn],tot;   
int f[maxnn][70];   
int arm[maxnn],armre[maxnn];   
int dep[maxnn];   
int mark[maxnn],mask[maxnn],mark1[maxnn];   
ll  dis1[maxnn];   
ll dis[maxnn][60];   
int size[maxnn];  
int tot1=0;  
typedef pair<ll ,ll > P;   
P a[maxnn],maj[maxnn];int c[maxnn];   
int cnt=0;   

void add(int a,int b,ll c)   
{   
    en[++tot]=b;   
    nex[tot]=las[a];   
    las[a]=tot;   
    le[tot]=c;  
}   
ll go_up(ll s,int x)   
{   
    int k=ceil(log2(dep[x]));   
    for(int i=k;i>=0;i--)   
    {   
        if(f[x][i]&&s>=(dis[x][i])) {s-=dis[x][i];x=f[x][i];}   
    }   
    return x;   
}   
void dfs(int v,int fa,ll l)   
{   
    dep[v]=dep[fa]+1;   
    dis[v][0]=l;   
    dis1[v]=dis1[fa]+l;   
    f[v][0]=fa;   
    size[v]=1;  
    int s=ceil(log2(dep[v]));   
    for(int i=1;i<=s;i++)   
    {   
        f[v][i]=f[f[v][i-1]][i-1];   
        dis[v][i]=dis[v][i-1]+dis[f[v][i-1]][i-1];   
    }   
    for(int i=las[v];i;i=nex[i])   
    {   
        int u=en[i];   
        if(u!=f[v][0])   
        {   
            dfs(u,v,le[i]);  
            size[v]+=size[u];   
        }   
    }   
}   
bool  dfs1(int fff,int v)   
{   int FLA = . 1 ;
       IF (MARK1 [V]) C [V] = FFF;   
     IF (Mark [V]) return  to true ;  
     IF ((size [V] == . 1 ) && ((Mark [V]))! )   return  to false ;       
     the else     
    {    
    
        for ( int I = Las [V]; I; I = NEX [I])    
        {    
                int U = EN [I];   
                 IF ! (U = F [V] [ 0 ])    
                {    
                   IF ( ! DFS1 (FFF, U)) FLA = 0 ; // this is a problem for a long time cards 
                }    
        }    
    } 
    IF(fla==0) return false;   
    return true;   
}   
bool isok(long long ttt)   
{   
    tot1=0;cnt=0;  
    for(int i=1;i<=n;i++) mark[i]=0,mark1[i]=0,mask[i]=0;   
    for(int i=1;i<=m;i++)   
    {   
        armre[i]=go_up(ttt,arm[i]);   
        if(armre [i] == 1 ) {MARK1 [arm [i]] = 1 ; A [++ tot1] .first = ttt-dis1 [arm [i]], A [tot1] .second = arm [i];}   
         else mark [armre [i]] = 1 ;   
    }    
    For ( int i = las [ 1 ]; i; i = nex [i])   
     if (! Dfs1 (one [i]; a [i]))    
    {    
        May [ ++ cnt] .first = le [i] ;   
        May [cnt] .second = one [i]; 
        mask the [a [i]] = 1 ;   
    }    
    Int i = 1 , j = 1 ;   
    black (a+1,a+1+tot1);  
    sort(maj+1,maj+1+cnt);  
    while(i<=tot1&&j<=cnt)   
    {   
        if(a[i].first>=maj[j].first&&mask[maj[j].second])    
        {   
            if(mask[c[a[i].second]]) mask[c[a[i].second]]=0,i++;   
            else  mask[maj[j].second]=0,i++,j++;   
        }   
        else   
        {   
            if(!mask[maj[j].second]) j++;   
            else    
            if(a[i].first<maj[j].first)  
            { 
                 if(mask[c[a[i].second]]) mask[c[a[i].second]]=0,i++;   
                 else    i++; 
            } 
        }   
    }   
     j=0; 
    for(int i=1;i<=cnt;i++) if(!mask[maj[i].second])j++; 
    return j>=cnt;   
}   
int main()   
{   
//freopen("xie.txt","r",stdin); 
//freopen("xiee.txt","w",stdout); 
    int x,y,z;   
    cin>>n;   
    ll l=0,r=1800000000;   
    for(int i=1;i<n;i++)   
    {   
        scanf("%d%d%d",&x,&y,&z);   
        add(x,y,z);   
        add(y,x,z);   
    }   
    cin>>m;   
    dfs(1,0,0);   
    for(int i=1;i<=m;i++)   
    {   
        scanf("%d",&arm[i]);   
    }   
    while(l<=r)   
    {   
        ll mid=(l+r)/2;   
        if(isok(mid))r=mid-1;   
        else l=mid+1;   
    }   
    if(l<=1800000000) 
    cout<<l;   
    else 
    cout<<-1; 
}

 

Guess you like

Origin www.cnblogs.com/OIEREDSION/p/11375248.html