看到題目後,顯然是求乙個最小的環。(把每個人看成點,關係看成邊。)
但是這裡可以對題目做乙個轉化。
可以發現每個人的只能有乙個目標點。
對於環上的點,顯然這個環上的任意乙個點都不會再往外走。那麼只存在別的點連入該環的情況。
別的點連入該環後,別的點顯然無法再成環。
那麼,我們可以將這些點都刪去,最後只留下所有的環。
如何刪點?首先可以發現,對於不成環的點,肯定存在乙個點入度為0.
那麼將這個入度為0的點刪去,然後將這個點的目標點的入度也-1。
注意的是,可能我們在刪去乙個點後,前面的點也變成入度為0了,所以在每次刪點後,判斷目標點也也是否需要刪去。
然後刪過的點就不要刪了,打上標記。
注意這樣處理後,如果去遍歷環上的所有點,複雜度還是o(n^2),會t。
但是我們可以發現,對於環上的任意一點,他們的完成時間都是一樣的。
那麼我們在遍歷乙個環時,將環上的所有點都打上標記,乙個環只遍歷一次。
複雜度就降到了o(n)左右。
code:
#includeusingview codenamespace
std;
typedef
long
long
ll;typedef pair
pii;
const
int n = 2e5+5
;const
int m = 4005*4005
;#define pi acos(-1)
#define inf 1e8
#define inm int_min
#define dbg(ax) cout << "now this num is " << ax << endl;inline
intread()
while(c >= '
0' && c <= '9')
return x*f;
}int to[n],in[n],vis[n],ans =inf;
void delete(int
x)void dfs(int x,int rt,int
sum)
dfs(to[x],rt,sum+1);}
intmain()
for(int i = 1;i <= n;++i) if(in[i] == 0 && !vis[i]) delete(i);
for(int i = 1;i <= n;++i) if(in[i] != 0 && !vis[i]) dfs(i,i,0
); printf(
"%d\n
",ans);
system(
"pause");
return0;
}
洛谷2661 資訊傳遞
題目描述 有n個同學 編號為1到n 正在玩乙個資訊傳遞的遊戲。在遊戲裡每人都有乙個固定的資訊傳遞物件,其中,編號為i的同學的資訊傳遞物件是編號為ti同學。遊戲開始時,每人都只知道自己的生日。之後每一輪中,所有人會同時將自己當前所知的生日資訊告訴各自的資訊傳遞物件 注意 可能有人可以從若干人那裡獲取資...
洛谷P2661 資訊傳遞
有n個同學 編號為1到n 正在玩乙個資訊傳遞的遊戲。在遊戲裡每人都有乙個固定的資訊傳遞物件,其中,編號為i的同學的資訊傳遞物件是編號為ti同學。遊戲開始時,每人都只知道自己的生日。之後每一輪中,所有人會同時將自己當前所知的生日資訊告訴各自的資訊傳遞物件 注意 可能有人可以從若干人那裡獲取資訊,但是每...
洛谷 P2661 資訊傳遞
有 n個同學 編號為1到 n 正在玩乙個資訊傳遞的遊戲。在遊戲裡每人都有乙個固定的資訊傳遞物件,其中,編號為 i的同學的資訊傳遞物件是編號為 ti同學。遊戲開始時,每人都只知道自己的生日。之後每一輪中,所有人會同時將自己當前所知的生日資訊告訴各自的資訊傳遞物件 注意 可能有人可以從若干人那裡獲取資訊...