洛谷 P2921 在农场万圣节Trick or Treat on the Farm题解
題意翻譯
題目描述
每年,在威斯康星州,奶牛們都會穿上衣服,收集農(nóng)夫約翰在N(1<=N<=100,000)個牛棚隔間中留下的糖果,以此來慶祝美國秋天的萬圣節(jié)。
由于牛棚不太大,FJ通過指定奶牛必須遵循的穿越路線來確保奶牛的樂趣。為了實現(xiàn)這個讓奶牛在牛棚里來回穿梭的方案,FJ在第i號隔間上張貼了一個“下一個隔間”Next_i(1<=Next_i<=N),告訴奶牛要去的下一個隔間;這樣,為了收集它們的糖果,奶牛就會在牛棚里來回穿梭了。
FJ命令奶牛i應(yīng)該從i號隔間開始收集糖果。如果一只奶牛回到某一個她已經(jīng)去過的隔間,她就會停止收集糖果。
在被迫停止收集糖果之前,計算一下每頭奶牛要前往的隔間數(shù)(包含起點)。
輸入格式
第1行 整數(shù)n。
第2行到n+1行 每行包含一個整數(shù) next_i 。
輸出格式
n行,第i行包含一個整數(shù),表示第i只奶牛要前往的隔間數(shù)。
樣例解釋
有4個隔間
隔間1要求牛到隔間1
隔間2要求牛到隔間3
隔間3要求牛到隔間2
隔間4要求牛到隔間3
牛1,從1號隔間出發(fā),總共訪問1個隔間;
牛2,從2號隔間出發(fā),然后到三號隔間,然后到2號隔間,終止,總共訪問2個隔間;
牛3,從3號隔間出發(fā),然后到2號隔間,然后到3號隔間,終止,總共訪問2個隔間;
牛4,從4號隔間出發(fā),然后到3號隔間,然后到2號隔間,然后到3號隔間,終止,總共訪問3個隔間。
翻譯提供者:吃葡萄吐糖
題目描述
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.
?
題解
這個題雖然是圖的題目,但是它的圖很特殊,每個節(jié)點的出度都是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迷宮問題的思路類似,需要對圖進行染色,找到環(huán),同一個環(huán)上的各個節(jié)點的隔間數(shù)是相同的,把這個結(jié)果保存下來就可以減少后續(xù)的運算量了。下圖是樣例染色的結(jié)果。1號節(jié)點是個自環(huán)長度為1,2和3號節(jié)點是長度為2的環(huán),所以這兩個節(jié)點輸出的隔間數(shù)都是環(huán)的長度2。4號節(jié)點經(jīng)過1步走到2和3組成的環(huán),所以它的隔間數(shù)是1+2=3。
?染色的過程有兩種可能:
1)染色的過程遇到了同種顏色的節(jié)點,例如下圖中2-3-4-3。
2)染色的過程中遇到了不同顏色的節(jié)點,例如下圖中的5-2和6-4。
為了方便計算環(huán)的長度和走過的隔間數(shù),我們引入兩個變量:cnt和dfn數(shù)組。cnt從0開始,用于計算此次染色所經(jīng)過的隔間數(shù),每走一次加1。dfn記錄每個節(jié)點和此次染色第一個節(jié)點之間的距離。例如第一種染色情況,dfn(2)=0,dfn(3)=1,dfn(4)=2。當(dāng)從4走到3時,我們立刻可以發(fā)現(xiàn)一個同色節(jié)點組成的環(huán)。環(huán)的長度是cnt-dfn(3)=2。而且我們可以記錄下這個顏色路徑進入環(huán)的第一個節(jié)點是3號節(jié)點。
對于第2種染色過程,又分為兩種情況:
1)所遇到的不同顏色的節(jié)點在環(huán)上,如4號節(jié)點。這種情況隔間數(shù)等于cnt+環(huán)長。
2)所遇到的不同顏色的節(jié)點不在環(huán)上,如2號節(jié)點。這種情況隔間數(shù)等于cnt+環(huán)長+從所遇到的節(jié)點到第一個進入環(huán)的節(jié)點的距離。
而判斷節(jié)點是否在環(huán)上,可以用dfn的大小進行比較,所有比第一個進入環(huán)的節(jié)點的dfn小的節(jié)點都在環(huán)外,反之在環(huá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)長 13 int stloop[MAXN]; // 路徑中進入環(huán)的第一個節(jié)點的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 { // 走到了其他點染色的路徑 43 looplen[i] = looplen[vis[p]]; 44 stloop[i] = cnt; 45 if(stloop[vis[p]] > dfn[p]) 46 { // 遇到的點不在環(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题解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 02(c)多元无约束优化问题-牛顿法
- 下一篇: C#图片处理