洛谷 P2921 在农场万圣节Trick or Treat on the Farm题解
題意翻譯
題目描述
每年,在威斯康星州,奶牛們都會(huì)穿上衣服,收集農(nóng)夫約翰在N(1<=N<=100,000)個(gè)牛棚隔間中留下的糖果,以此來慶祝美國(guó)秋天的萬圣節(jié)。
由于牛棚不太大,FJ通過指定奶牛必須遵循的穿越路線來確保奶牛的樂趣。為了實(shí)現(xiàn)這個(gè)讓奶牛在牛棚里來回穿梭的方案,FJ在第i號(hào)隔間上張貼了一個(gè)“下一個(gè)隔間”Next_i(1<=Next_i<=N),告訴奶牛要去的下一個(gè)隔間;這樣,為了收集它們的糖果,奶牛就會(huì)在牛棚里來回穿梭了。
FJ命令奶牛i應(yīng)該從i號(hào)隔間開始收集糖果。如果一只奶牛回到某一個(gè)她已經(jīng)去過的隔間,她就會(huì)停止收集糖果。
在被迫停止收集糖果之前,計(jì)算一下每頭奶牛要前往的隔間數(shù)(包含起點(diǎn))。
輸入格式
第1行 整數(shù)n。
第2行到n+1行 每行包含一個(gè)整數(shù) next_i 。
輸出格式
n行,第i行包含一個(gè)整數(shù),表示第i只奶牛要前往的隔間數(shù)。
樣例解釋
有4個(gè)隔間
隔間1要求牛到隔間1
隔間2要求牛到隔間3
隔間3要求牛到隔間2
隔間4要求牛到隔間3
牛1,從1號(hào)隔間出發(fā),總共訪問1個(gè)隔間;
牛2,從2號(hào)隔間出發(fā),然后到三號(hào)隔間,然后到2號(hào)隔間,終止,總共訪問2個(gè)隔間;
牛3,從3號(hào)隔間出發(fā),然后到2號(hào)隔間,然后到3號(hào)隔間,終止,總共訪問2個(gè)隔間;
牛4,從4號(hào)隔間出發(fā),然后到3號(hào)隔間,然后到2號(hào)隔間,然后到3號(hào)隔間,終止,總共訪問3個(gè)隔間。
翻譯提供者:吃葡萄吐糖
題目描述
Every year in Wisconsin the cows celebrate the USA autumn holiday of Halloween by dressing up in costumes and collecting candy that Farmer John leaves in the N (1 <= N <= 100,000) stalls conveniently numbered 1..N.
Because the barn is not so large, FJ makes sure the cows extend their fun by specifying a traversal route the cows must follow. To implement this scheme for traveling back and forth through the barn, FJ has posted a 'next stall number' next_i (1 <= next_i <= N) on stall i that tells the cows which stall to visit next; the cows thus might travel the length of the barn many times in order to collect their candy.
FJ mandates that cow i should start collecting candy at stall i. A cow stops her candy collection if she arrives back at any stall she has already visited.
Calculate the number of unique stalls each cow visits before being forced to stop her candy collection.
POINTS: 100
輸入格式
* Line 1: A single integer: N
* Lines 2..N+1: Line i+1 contains a single integer: next_i
輸出格式
* Lines 1..N: Line i contains a single integer that is the total number of unique stalls visited by cow i before she returns to a stall she has previously visited.
輸入輸出樣例
輸入 #1復(fù)制 4 1 3 2 3 輸出 #1復(fù)制 1 2 2 3說明/提示
Four stalls.
* Stall 1 directs the cow back to stall 1.
* Stall 2 directs the cow to stall 3
* Stall 3 directs the cow to stall 2
* Stall 4 directs the cow to stall 3
Cow 1: Start at 1, next is 1. Total stalls visited: 1.
Cow 2: Start at 2, next is 3, next is 2. Total stalls visited: 2. Cow 3: Start at 3, next is 2, next is 3. Total stalls visited: 2. Cow 4: Start at 4, next is 3, next is 2, next is 3. Total stalls visited: 3.
?
題解
這個(gè)題雖然是圖的題目,但是它的圖很特殊,每個(gè)節(jié)點(diǎn)的出度都是1,而且一定存在環(huán)。
直接暴力可以得40分。
#include <iostream> #include <stdio.h> #include <math.h> #include <algorithm> #include <string.h>using namespace std;const int MAXN = 1e5 + 5; int n, next[MAXN], vis[MAXN], ans[MAXN], p; int main() {cin >> n;for(int i = 1; i <= n; i++){cin >> next[i];}for(int i = 1; i <= n; i++){memset(vis, 0, sizeof(vis));ans[i] = 1;p = i;vis[p] = 1;while(vis[next[p]] == 0){vis[next[p]] = 1;p = next[p];ans[i]++;}}for(int i = 1; i <= n; i++){cout << ans[i] << endl;}return 0; }剩下的問題就是如何解決TLE的問題。和01迷宮問題的思路類似,需要對(duì)圖進(jìn)行染色,找到環(huán),同一個(gè)環(huán)上的各個(gè)節(jié)點(diǎn)的隔間數(shù)是相同的,把這個(gè)結(jié)果保存下來就可以減少后續(xù)的運(yùn)算量了。下圖是樣例染色的結(jié)果。1號(hào)節(jié)點(diǎn)是個(gè)自環(huán)長(zhǎng)度為1,2和3號(hào)節(jié)點(diǎn)是長(zhǎng)度為2的環(huán),所以這兩個(gè)節(jié)點(diǎn)輸出的隔間數(shù)都是環(huán)的長(zhǎng)度2。4號(hào)節(jié)點(diǎn)經(jīng)過1步走到2和3組成的環(huán),所以它的隔間數(shù)是1+2=3。
?染色的過程有兩種可能:
1)染色的過程遇到了同種顏色的節(jié)點(diǎn),例如下圖中2-3-4-3。
2)染色的過程中遇到了不同顏色的節(jié)點(diǎn),例如下圖中的5-2和6-4。
為了方便計(jì)算環(huán)的長(zhǎng)度和走過的隔間數(shù),我們引入兩個(gè)變量:cnt和dfn數(shù)組。cnt從0開始,用于計(jì)算此次染色所經(jīng)過的隔間數(shù),每走一次加1。dfn記錄每個(gè)節(jié)點(diǎn)和此次染色第一個(gè)節(jié)點(diǎn)之間的距離。例如第一種染色情況,dfn(2)=0,dfn(3)=1,dfn(4)=2。當(dāng)從4走到3時(shí),我們立刻可以發(fā)現(xiàn)一個(gè)同色節(jié)點(diǎn)組成的環(huán)。環(huán)的長(zhǎng)度是cnt-dfn(3)=2。而且我們可以記錄下這個(gè)顏色路徑進(jìn)入環(huán)的第一個(gè)節(jié)點(diǎn)是3號(hào)節(jié)點(diǎn)。
對(duì)于第2種染色過程,又分為兩種情況:
1)所遇到的不同顏色的節(jié)點(diǎn)在環(huán)上,如4號(hào)節(jié)點(diǎn)。這種情況隔間數(shù)等于cnt+環(huán)長(zhǎng)。
2)所遇到的不同顏色的節(jié)點(diǎn)不在環(huán)上,如2號(hào)節(jié)點(diǎn)。這種情況隔間數(shù)等于cnt+環(huán)長(zhǎng)+從所遇到的節(jié)點(diǎn)到第一個(gè)進(jìn)入環(huán)的節(jié)點(diǎn)的距離。
而判斷節(jié)點(diǎn)是否在環(huán)上,可以用dfn的大小進(jìn)行比較,所有比第一個(gè)進(jìn)入環(huán)的節(jié)點(diǎn)的dfn小的節(jié)點(diǎn)都在環(huán)外,反之在環(huán)上。
下面就是改進(jìn)后的代碼:
1 #include <iostream> 2 #include <stdio.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <string.h> 6 7 using namespace std; 8 9 const int MAXN = 1e5 + 5; 10 int n, next[MAXN], vis[MAXN], ans[MAXN], p; 11 int dfn[MAXN], cnt; 12 int looplen[MAXN]; // 環(huán)長(zhǎng) 13 int stloop[MAXN]; // 路徑中進(jìn)入環(huán)的第一個(gè)節(jié)點(diǎn)的dfn值 14 15 int main() 16 { 17 cin >> n; 18 for(int i = 1; i <= n; i++) 19 { 20 cin >> next[i]; 21 } 22 23 memset(vis, 0, sizeof(vis)); 24 for(int i = 1; i <= n; i++) 25 { 26 cnt = 0; 27 p = i; 28 while(vis[p] == 0) 29 { 30 vis[p] = i; 31 dfn[p] = cnt; 32 p = next[p]; 33 cnt++; 34 } 35 if(vis[p] == i) 36 { // 走到了自己染色的環(huán) 37 ans[i] = cnt; 38 looplen[i] = cnt - dfn[p]; 39 stloop[i] = dfn[p]; 40 } 41 else 42 { // 走到了其他點(diǎn)染色的路徑 43 looplen[i] = looplen[vis[p]]; 44 stloop[i] = cnt; 45 if(stloop[vis[p]] > dfn[p]) 46 { // 遇到的點(diǎn)不在環(huán)上 47 stloop[i] += stloop[vis[p]] - dfn[p]; 48 } 49 ans[i] = stloop[i] + looplen[i]; 50 } 51 } 52 for(int i = 1; i <= n; i++) 53 { 54 cout << ans[i] << endl; 55 } 56 57 return 0; 58 }?
?
轉(zhuǎn)載于:https://www.cnblogs.com/zealsoft/p/11406232.html
總結(jié)
以上是生活随笔為你收集整理的洛谷 P2921 在农场万圣节Trick or Treat on the Farm题解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 02(c)多元无约束优化问题-牛顿法
- 下一篇: 【资讯】2017年最好的25大发明,你最