1. 程式人生 > >洛谷 P3942 將軍令 解題報告

洛谷 P3942 將軍令 解題報告

一支 一行 完全 關於 超過 i++ 特殊性 include ext

P3942 將軍令

題目描述

又想起了四月。

如果不是省選,大家大概不會這麽輕易地分道揚鑣吧? 只見一個又一個昔日的隊友離開了機房。

憑君莫話封侯事,一將功成萬骨枯。

夢裏,小\(F\)成了一個給將軍送密信的信使。

現在,有兩封關乎國家生死的密信需要送到前線大將軍帳下,路途兇險,時間緊迫。小\(F\)不因為自己的禍福而避趨之,勇敢地承擔了這個任務。

不過,小\(F\)實在是太粗心了,他一不小心把兩封密信中的一封給弄掉了。

\(F\)偷偷打開了剩下的那封密信。他 發現一副十分詳細的地圖,以及幾句批文——原來 這是戰場周圍的情報地圖。他仔細看後發現,在這張地圖上標記了\(n\)個從 1 到\(n\)

標號的 驛站,\(n?1\)條長度為1裏的小道,每條小道雙向連接兩個不同的驛站,並且驛站之間可以 通過小道兩兩可達。

\(F\)仔細辨認著上面的批註,突然明白了丟失的信的內容了。原來,每個驛站都可以駐 紮一個小隊,每個小隊可以控制距離不超過\(k\)裏的驛站。如果有驛站沒被控制,就容易產 生危險——因此這種情況應該完全避免。而那封丟失的密信裏,就裝著朝廷數學重臣留下的 精妙的排布方案,也就是用了最少的小隊來控制所有驛站。

\(F\)知道,如果能計算出最優方案的話,也許他就能夠將功贖過,免於死罪。他找到了 你,你能幫幫他嗎? 當然,小\(F\) 在等待你的支援的過程中,也許已經從圖上觀察出了一些可能會比較有用的 性質,他會通過一種特殊的方式告訴你。

輸入輸出格式

輸入格式:

從標準輸入中讀入數據。

輸入第 1 行一個正整數\(n,k,t\),代表驛站數,一支小隊能夠控制的最遠距離,以及特殊性質所代表的編號。關於特殊性質請參照數據範圍。

輸入第 2 行至第\(n\)行,每行兩個正整數\(u_i,v_i\),表示在\(u_i\)\(v_i\)間,有一條長度為 一裏的小道。

輸出格式:

輸出到標準輸出中。

輸出一行,為最優方案下需要的小隊數。

說明:

子任務會給出部分測試數據的特點。如果你在解決題目中遇到了困難,可以嘗試只解 決一部分測試數據。

關於 t 的含義如下: t = 0:該測試點沒有額外的特殊性質; t = 1:保證最多 8 個點的所連接的小道超過 1 條; t = 2:保證所有點到 1 號點的距離不超過 2。

每個測試點的數據規模及特點如下表

技術分享圖片


貪心策略:自下向上做,當一個點不得不需要照看的時候,進行照看。

正確性:保證了每個照看點盡可能的高,也就覆蓋的更多。即由最優推最優。

實現:在\(dfs\)過程中,每次從子節點接受一個值\(x\)

\(x>0\)時,代表當前節點存在至少一個比它低\(x-1\)的節點需要照看

\(x<=0\)時,代表當前節點還可以覆蓋離它距離不超過\(-x\)的點

對每個節點找到最大正值和最小非負值,看看能否用負的照看正的。

復雜度:\(O(n)\)


Code:

#include <cstdio>
const int N=100010;
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{
    to[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
}
int n,used[N],ans=0,k,t;
void init()
{
    scanf("%d%d%d",&n,&k,&t);
    int u,v;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
}
int dfs(int now)
{
    int mx=1,mi=1;
    used[now]=1;
    for(int i=head[now];i;i=Next[i])
    {
        int v=to[i];
        if(!used[v])
        {
            int x=dfs(v);
            if(x>0) mx=mx>x?mx:x;
            else  mi=mi<x?mi:x;
        }
    }
    if(-mi>=mx-1) return mi+1;
    if(mx<=k) return mx+1;
    ans++;
    return -k+1;
}
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("wr.out","w",stdout);
    init();
    if(k&&dfs(1)>k) ans++;
    printf("%d\n",ans);
    return 0;
}

2018.7.11

洛谷 P3942 將軍令 解題報告