LA3902网络

题意:
     给你一棵树,所有叶子节点都是客户端,其他的都是服务器,然后问你最少在多少个服务器上安装VOD能使所有的客户端都能流畅的看视频,流畅看视频的条件是每个客户端距离他最近的安装VOD的服务器的距离不能超过k,而且题目已经给你在一个服务器上安装好了VOD。


思路:
     自己没想出来,说下白书上的思路,第一个就是说当遇到无根树的时候,一般情况下把无根树变成有根数会有利于问题的解决,然后这个题目就是把给定的VOD服务器变成了树根,然后我们可以根据贪心策略,先处理深度最深的,安装VOD是在当前深度最深的上面第k个父亲那安装VOD这样是为了尽可能多的去让别的客户端能用上这个VOD,然后就是模拟这个过程了,这个思路是白书上说的,我想了一阵子,只是感觉有道理,但并不能肯定他的正确性,说白了就是还没弄清楚这样为什么是对的,以后会重新编辑这篇博客。
     


#include<stdio.h>
#include<string.h>


#define N 1000+5
#define N_node 1000 + 5
#define N_edge 2000 + 10


typedef struct
{
   int to ,next;
}STAR;


STAR E[N_edge];
int list[N_node] ,tot;


int mark[N] ,mk[N] ,deep[N];
int dis[N][N] ,mer[N];


void add(int a ,int b)
{
   E[++tot].to = b;
   E[tot].next = list[a];
   list[a] = tot;
}


//deep mark


void DFS1(int s ,int fa)
{
   int mk = 0;
   for(int k = list[s] ;k ;k = E[k].next)
   {
       int to = E[k].to;
       if(to == fa) continue;
       mk = 1;
       mer[to] = s;
       deep[to] = deep[s] + 1;
       DFS1(to ,s);
   }
   mark[s] = !mk;
}


//dis
void DFS2(int sss ,int now ,int s ,int fa)
{
    for(int k = list[s] ;k ;k = E[k].next)
    {
        int to = E[k].to;
        if(to == fa) continue;
        dis[sss][to] = now;
        DFS2(sss ,now + 1 ,to ,s);
    }
}


int main ()
{
    int n ,s ,k ,i ,j ,t ,a ,b;
    scanf("%d" ,&t);
    while(t--)
    {
        scanf("%d %d %d" ,&n ,&s ,&k);
        memset(list ,0 ,sizeof(list)) ,tot = 1;
        for(i = 1 ;i < n ;i ++)
        {
            scanf("%d %d" ,&a ,&b);
            add(a ,b) ,add(b ,a);
        }
        for(i = 1 ;i <= n ;i ++) mer[i] = i;
        deep[s] = 0;
        DFS1(s ,-1);
        for(i = 1 ;i <= n ;i ++)
        {
           dis[i][i] = 0;
           DFS2(i ,1 ,i ,-1);
        }
         
        memset(mk ,0 ,sizeof(mk));
        for(i = 1 ;i <= n ;i ++)
        if(mark[i] && dis[s][i] <= k) 
        mk[i] = 1;
        int Ans = 0;
        while(1)
        {
            int mkid = 0 ,maxdeep = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                if(!mark[i] || mk[i]) continue;
                if(maxdeep < deep[i])
                maxdeep = deep[i] ,mkid = i;
            }
            if(!mkid) break;        
            Ans ++;
            int maxdis = 0 ,mknode = 0;
            mknode = mkid;
            for(i = 1 ;i <= k ;i ++)
            mknode = mer[mknode];
            for(i = 1 ;i <= n ;i ++)
            {
                if(!mark[i] || mk[i]) continue;
                if(dis[mknode][i] <= k) mk[i] = 1;
            }
        }
        printf("%d " ,Ans);
    }
    return 0;
}    
        
           
            
        







原文地址:https://www.cnblogs.com/csnd/p/12062642.html