luogu P3942 將軍令
題目背景
pdf題面和大樣例鏈接:http://pan.baidu.com/s/1cawM7c 密碼:xgxv
歷史/落在/贏家/之手
至少/我們/擁有/傳說
誰說/敗者/無法/不朽
拳頭/只能/讓人/低頭
念頭/卻能/讓人/擡頭
擡頭/去看/去愛/去追
你心中的夢
題目描述
又想起了四月。
如果不是省選,大家大概不會這麽輕易地分道揚鑣吧? 只見一個又一個昔日的隊友離開了機房。
憑君莫話封侯事,一將功成萬骨枯。
夢裏,小 F 成了一個給將軍送密信的信使。
現在,有兩封關乎國家生死的密信需要送到前線大將軍帳下,路途兇險,時間緊迫。小 F 不因為自己的禍福而避趨之,勇敢地承擔了這個任務。
不過,小 F 實在是太粗心了,他一不小心把兩封密信中的一封給弄掉了。
小 F 偷偷打開了剩下的那封密信。他 發現一副十分詳細的地圖,以及幾句批文——原來 這是戰場周圍的情報地圖。他仔細看後發現,在這張地圖上標記了 n 個從 1 到 n 標號的 驛站,n − 1 條長度為 1 裏的小道,每條小道雙向連接兩個不同的驛站,並且驛站之間可以 通過小道兩兩可達。
小 F 仔細辨認著上面的批註,突然明白了丟失的信的內容了。原來,每個驛站都可以駐 紮一個小隊,每個小隊可以控制距離不超過 k 裏的驛站。如果有驛站沒被控制,就容易產 生危險——因此這種情況應該完全避免。而那封丟失的密信裏,就裝著朝廷數學重臣留下的 精妙的排布方案,也就是用了最少的小隊來控制所有驛站。
小 F 知道,如果能計算出最優方案的話,也許他就能夠將功贖過,免於死罪。他找到了 你,你能幫幫他嗎? 當然,小 F 在等待你的支援的過程中,也許已經從圖上觀察出了一些可能會比較有用的 性質,他會通過一種特殊的方式告訴你。
輸入輸出格式
輸入格式:
從標準輸入中讀入數據。
輸入第 1 行一個正整數 n,k,t,代表驛站數,一支小隊能夠控制的最遠距離,以及特 殊性質所代表的編號。關於特殊性質請參照數據範圍。
輸入第 2 行至第 n 行,每行兩個正整數 ui?,vi?,表示在 ui? 和 vi? 間,有一條長度為 一裏的小道。
輸出格式:
輸出到標準輸出中。
輸出一行,為最優方案下需要的小隊數。
輸入輸出樣例
輸入樣例#1: 復制4 1 0
1 2
1 3
1 4
輸出樣例#1: 復制
1
輸入樣例#2: 復制
6 1 0
1 2
1 3
1 4
4 5
4 6
輸出樣例#2: 復制
2
說明
【樣例 1 說明】
如圖。由於一號節點到周圍的點距離均是 1,因此可以控制所有驛站。
【樣例 2 說明】
如圖,和樣例 1 類似。
子任務會給出部分測試數據的特點。如果你在解決題目中遇到了困難,可以嘗試只解 決一部分測試數據。
關於 t 的含義如下: t = 0:該測試點沒有額外的特殊性質; t = 1:保證最多 8 個點的所連接的小道超過 1 條; t = 2:保證所有點到 1 號點的距離不超過 2。
每個測試點的數據規模及特點如下表
題目鏈接:https://www.luogu.org/problemnew/show/P3942#sub
解題報告:
低配版消防局
bfs+dfs+貪心
從最深處開始貪心,將其k祖先作為驛站,進行dfs
#include<cstdio> #include<queue> #include<algorithm> #include<iostream> #define BIG 2000011 #define ll long long #define FOR(i,s,t) for(register int i=s;i<=t;++i) using namespace std; int nxt[BIG],las[BIG>>1],to[BIG],a[BIG>>1],dep[BIG>>1],fa[BIG>>1],vis[BIG>>1]; int n,k,t,f; int x,y,ans,tot; inline void add(int x,int y){ nxt[++tot]=las[x];las[x]=tot;to[tot]=y; } #define VIS(now) for(register int e=las[now];e;e=nxt[e]) inline void bfs(int x){ queue<int>q; dep[x]=1; fa[1]=1; q.push(x); int now; while(!q.empty()){ now=q.front(); q.pop(); VIS(now) if(!dep[to[e]]) fa[to[e]]=now,dep[to[e]]=dep[now]+1,q.push(to[e]); } } inline bool cmp(int a,int b){ return dep[a]>dep[b]; } inline int up(int x){ int cnt=0; while(cnt<k){ x=fa[x]; ++cnt; } return x; } inline void dfs(int now,int fa,int tot){ vis[now]=1; if(tot==k) return; VIS(now) if(to[e]!=fa) dfs(to[e],now,tot+1); } int main(){ scanf("%d%d%d",&n,&k,&t); FOR(i,2,n){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } bfs(1); FOR(i,1,n) a[i]=i; sort(a+1,a+n+1,cmp); FOR(i,1,n) if(!vis[a[i]]){ ++ans; f=up(a[i]); dfs(f,f,0); } printf("%d\n",ans); return 0; }
luogu P3942 將軍令