UVA - 1267(贪心)

先根据根服务器位置,将五根树转换为有根树,

然后,每次深度最大的未被覆盖到的节点,选其k级祖先做服务器、证明,就是假设法。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cctype>
using namespace std;
typedef long long LL;
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep1(i,n) for(int (i)=1;(i)<=(n);(i)++)
const int maxn = 1110;
vector<int> G[maxn];
int sx,k,n;
struct node{
  int id,dep;
  bool operator <(const node& a)const{
    return dep<a.dep;
  }
}a[maxn];
int fat[maxn];
vector<node> ans;
void dfs(int u,int fa,int depth){
  a[u].id = u; a[u].dep = depth;
  fat[u] = fa;
  if(G[u].size()==1&&G[u][0]==fa){
      if(depth > k) ans.push_back(a[u]);
      return ;
  }
  for(int i=0;i<G[u].size();i++){
      int v = G[u][i];
      if(v==fa) continue;
      dfs(v,u,depth+1);
  }
}
int vis[maxn];
void kuo(int u,int fa,int tk){
   vis[u] = 1;
   for(int i=0;i<G[u].size();i++){
      int v = G[u][i];
      if(v == fa) continue;
      if(tk<k) kuo(v,u,tk+1);
   }
}
int find_fa(int x,int d){
  return (d == k ? x:find_fa(fat[x],d+1));
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
      scanf("%d %d %d",&n,&sx,&k);
      rep1(i,n) G[i].clear();
      rep(i,n-1){
        int x,y;
        scanf("%d %d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
      }
      ans.clear();
      dfs(sx,-1,0);
      memset(vis,0,sizeof(vis));
      if(ans.size()>0){
        sort(ans.begin(),ans.end());
      }
      int res = 0;
      kuo(sx,-1,0);
      if(ans.size()>0)
      for(int i=ans.size()-1;i>=0;i--){
         int v = ans[i].id;
         if(!vis[v]){
            kuo(find_fa(v,0),-1,0);
            res++;
         }
      }
      printf("%d\n",res);
    }
    return 0;
}



你可能感兴趣的:(算法竞赛入门经典,入门题)