UVALive - 3902 Network 網絡
題目大意:
n臺機器連成一個樹狀網絡,其中葉節點是客戶端,其他節點是服務器。現在有一臺服務器在節點s,服務器能傳播的信號的距離爲k,因爲有的用戶距離服務器的距離大於k,所以必須添加服務器。問最少要添加幾個服務器,才能使每個客戶端都收到信號。
解題思路:
用 STL 的 vector 建圖,一個 G[maxN] 存儲圖的信息 ;同時用 P[dis] 存儲深度大於 k ( 存儲的葉子節點的深度即爲 dis )的葉子節點;此外還要記錄下每個節點的雙親(即以 s 爲根將此圖轉化爲有根樹)。
對P[dis] 從dis最大處遍歷到最小處 ,用 coverd 標記已經被服務器覆蓋的節點, 當遇到沒有被覆蓋的葉子節點時, ans++ 。
上個過程,遇到沒有被覆蓋的葉子節點時,服務器要設立在此葉子節點的前 k 代祖先處。
AC代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include<vector>
#define rep(i,l,p) for(int i=l;i<=p;i++)
#define rush() int T; scanf("%d",&T); while(T--)
using namespace std;
const int maxN = 1005;
const int maxM = 1000005;
int n,s,k,pars[maxN];
vector<int> G[maxN],P[maxN];
int coverd[maxN];
void dfs(int u,int par,int dis){
pars[u] = par;
for(int i = 0; i<G[u].size();i++){
int v = G[u][i];
if ( v == par ) continue;
if ( dis +1 > k && G[v].size() == 1){
P[dis+1].push_back(v);
}
dfs(v,u,dis+1);
}
}
void dfs2(int u,int par,int dep){
if ( dep > k ) return;
coverd[u] = 1;
//int ecnt = G[u].size();
for(int i = 0; i <G[u].size(); i++){
int v = G[u][i];
// if ( coverd[v] ) continue;//下次到來可能可以走到更深
if(v != par)dfs2(v,u,dep+1);
}
}
int solve(){
int ans = 0;
for(int i = n-1;i>k;i--){
if (P[i].size()){
for(int j = 0;j<P[i].size();j++){
int anc = P[i][j];
if ( coverd[anc] ) continue;
rep(i,1,k){
anc = pars[anc];
}
ans++;
dfs2(anc,-1,0);
}
}
}
printf("%d\n", ans);
}
void input(){
memset(coverd,0,sizeof(coverd));
memset(pars,0,sizeof(pars));
scanf("%d%d%d",&n,&s,&k);
for(int i = 0;i<=n;i++){
if ( G[i].size() ) G[i].clear();
if ( P[i].size() ) P[i].clear(); //開始忘了初始化
}
//cout << n << s << k << endl;
int u,v;
rep(i,1,n-1){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(s,-1,0);
}
int main(int argc, char const *argv[])
{
//freopen("in.txt","r",stdin);
rush(){
input();
solve();
}
return 0;
}