1. 程式人生 > 實用技巧 >洛谷 P2661 資訊傳遞 題解

洛谷 P2661 資訊傳遞 題解

這道題根據題意可以理解為在圖中找一個最小環的問題

又因為題目中一條重要的性質:每個點出度都為1,所以我想到了一個刪邊的做法。

詳細來講就是遞迴刪去除環以外的邊(即原本或更新後入度為1的邊),剩下一個個獨立無交集的環,再遍歷一遍就能找出答案。

注:每個點在刪邊和搜環時只會遍歷一遍,所以程式並不會超時。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200010
#define int long long
#define rep(i,s,e) for(register int i=s;i<=e;++i)
#define
dwn(i,s,e) for(register int i=s;i>=e;--i) using namespace std; inline int read() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();} return f*x; } inline void write(int x) {
if(x<0){putchar('-');x=-x;} if(x>9)write(x/10); putchar(x%10+'0'); } int n,ans=99999999; int a[maxn],r[maxn],book[maxn]; void remove(int x) { --r[a[x]]; book[x]=-1; if(r[a[x]]==0&&book[a[x]]==0) remove(a[x]); } void dfs(int x,int st,int step) { // cout<<x<<" "<<st<<" "<<step<<endl;
// getchar(); if(x==st&&step!=0) { ans=min(ans,step); return; } book[x]=1; dfs(a[x],st,step+1); } signed main() { n=read(); rep(i,1,n) { a[i]=read(); ++r[a[i]]; } rep(i,1,n) { if(r[i]==0&&book[i]!=-1) remove(i); } rep(i,1,n) { if(book[i]==0) dfs(i,i,0); } cout<<ans; return 0; }