寒假刷題10:Network(LA 3902) 無根樹轉有根樹+貪心

題目鏈接:
Network

題目解析:

將原本的無根樹,以原始VOD服務器爲根,轉變爲有根樹.對於已經滿足條件的客戶端直接忽略.

將剩餘所有葉子節點按深度入隊,之後從最深的一層向上遍歷.如果發現未被覆蓋的葉子節點,就向上回溯k層後插入一個服務器.

每插入一個服務器,就進行一次DFS,覆蓋與它相距不超過k的所有葉子節點.

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<cmath>
#include<vector>
using namespace std;
#define ll long long

vector<int>gr[1010],nodes[1010];
int n,s,k,fa[1010],vis[1010];
void dfs(int u,int f,int d)
{
    fa[u]=f;
    int num=gr[u].size();
    if(num==1 && d>k) nodes[d].push_back(u);
    for(int i=0;i<num;i++)
    {
        int v=gr[u][i];
        if(v!=f) dfs(v,u,d+1);
    }
}
void ddfs(int u,int f,int d)
{
    vis[u]=1;
    int num=gr[u].size();
    for(int i=0;i<num;i++)
    {
        int v=gr[u][i];
        if(v!=f && d<k) ddfs(v,u,d+1);
    }
}
int slove()
{
    int ans=0;
    memset(vis,0,sizeof(vis));
    for(int d=n-1;d>k;d--)
        for(int i=0;i<nodes[d].size();i++)
        {
            int u=nodes[d][i];
            if(vis[u]) continue;

            int v=u;
            for(int j=0;j<k;j++) v=fa[v];
            ddfs(v,-1,0);
            ans++;
        }
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&s,&k);
        for(int i=1;i<=n;i++) {gr[i].clear(),nodes[i].clear();}
        for(int i=0;i<n-1;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            gr[a].push_back(b);
            gr[b].push_back(a);
        }
        dfs(s,-1,0);
        printf("%d\n",slove());
    }
}

發佈了56 篇原創文章 · 獲贊 22 · 訪問量 6305
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章