题目描述
每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N<=100,000)个牛棚隔间中留下的糖果,以此来庆祝美国秋天的万圣节。
由于牛棚不太大,FJ通过指定奶牛必须遵循的穿越路线来确保奶牛的乐趣。为了实现这个让奶牛在牛棚里来回穿梭的方案,FJ在第i号隔间上张贴了一个“下一个隔间”Next_i(1<=Next_i<=N),告诉奶牛要去的下一个隔间;这样,为了收集它们的糖果,奶牛就会在牛棚里来回穿梭了。
FJ命令奶牛i应该从i号隔间开始收集糖果。如果一只奶牛回到某一个她已经去过的隔间,她就会停止收集糖果。
在被迫停止收集糖果之前,计算一下每头奶牛要前往的隔间数(包含起点)。
输入格式
第1行 整数n。
第2行到n+1行 每行包含一个整数 next_i 。
输出格式
n行,第i行包含一个整数,表示第i只奶牛要前往的隔间数。
样例解释
有4个隔间
隔间1要求牛到隔间1
隔间2要求牛到隔间3
隔间3要求牛到隔间2
隔间4要求牛到隔间3
牛1,从1号隔间出发,总共访问1个隔间;
牛2,从2号隔间出发,然后到三号隔间,然后到2号隔间,终止,总共访问2个隔间;
牛3,从3号隔间出发,然后到2号隔间,然后到3号隔间,终止,总共访问2个隔间;
牛4,从4号隔间出发,然后到3号隔间,然后到2号隔间,然后到3号隔间,终止,总共访问3个隔间。
翻译提供者:吃葡萄吐糖
输入输出样例
输入 #1 <button class="copy-btn lfe-form-sz-middle" data-v-370e72e2="" data-v-52f2d52f="" style="border-color: #3498db; color: #3498db; user-select: auto;" type="button"> 复制 </button>
4 1 3 2 3
输出 #1 <button class="copy-btn lfe-form-sz-middle" data-v-370e72e2="" data-v-52f2d52f="" style="border-color: #3498db; color: #3498db; user-select: auto;" type="button"> 复制 </button> View Code
1 2 2 3
思路
显然要想回到本身房间需要经历一个环的过程。
对于每个起点来说,这个点要么在环上,要么可以通过一条链到达一个环然后再转回来。
可以用染色法对于每个强连通分量染色。
如果一个点在一个环里,它能得到的糖果数量就是环的大小。
如果不在环里,就dfs循着邻边直到找到环为止,它所得到的糖果数就是这条链(起点到环上一点的父亲节点)长+环的大小。
CODE
1 #include <bits/stdc++.h> 2 #define dbg(x) cout << #x << "=" << x << endl 3 4 using namespace std; 5 typedef long long LL; 6 const int maxn = 1e5 + 7; 7 8 int head[maxn], dfn[maxn], low[maxn], st[maxn]; 9 int cnt = 0, tot = 0, tim = 0, top = 1, n, cl = 0; 10 int vis[maxn]; 11 int color[maxn]; 12 int ans[maxn]; 13 int nxt[maxn]; 14 int circle_size[maxn]; 15 16 /* 17 head[],结构体edge:存边 18 19 dfn[],low[]:tarjan中数组 20 21 st[]:模拟栈 22 23 out[]:出边 24 25 sd[]:强连通分量存储 26 27 dq[]:统计答案 28 */ 29 30 template<class T>inline void read(T &res) 31 { 32 char c;T flag=1; 33 while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; 34 while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; 35 } 36 37 struct Edge{ 38 int nxt, to; 39 }edge[maxn * 2]; 40 41 inline void BuildGraph(int from, int to) 42 { 43 cnt++; 44 edge[cnt].to = to; 45 edge[cnt].nxt = head[from]; 46 head[from] = cnt; 47 } 48 49 void tarjan(int x) 50 { 51 tim++; 52 dfn[x] = low[x] = tim; 53 st[top] = x; 54 top++; 55 vis[x] = 1; 56 for(int i = head[x] ; i != 0; i = edge[i].nxt) 57 { 58 int u = edge[i].to; 59 if(vis[u] == 0) 60 { 61 tarjan(u); 62 low[x]=min(low[x],low[u]); 63 } 64 else if(vis[u] == 1) 65 low[x]=min(low[x],dfn[u]); 66 } 67 if(dfn[x] == low[x]) 68 { 69 cl++; 70 do 71 { 72 top--; 73 color[st[top]] = cl; 74 vis[st[top]] = -1; 75 }while( st[top] != x ); 76 } 77 return ; 78 } 79 80 void dfs(int u, int x, int step) { 81 if(ans[x] != 0) { 82 ans[u] = ans[x] + step; 83 return ; 84 } 85 else dfs(u, nxt[x], step+1); 86 } 87 88 int main() 89 { 90 scanf("%d",&n); 91 for ( int i = 1; i <= n; ++i ) { 92 scanf("%d",&nxt[i]); 93 BuildGraph(i, nxt[i]); 94 if(i == nxt[i]) { 95 ans[i] = 1; 96 } 97 } 98 for ( int i = 1; i <= n; ++i ) { 99 if( !vis[i] ) { 100 tarjan(i); 101 } 102 } 103 for ( int i = 1; i <= n; ++i) { 104 circle_size[color[i]]++; 105 } 106 for ( int i = 1; i <= n; ++i) { 107 if(circle_size[color[i]] != 1) { 108 ans[i] = circle_size[color[i]]; 109 } 110 } 111 for ( int i = 1; i <= n; ++i) { 112 if(ans[i] == 0) { 113 dfs(i, nxt[i], 1); 114 } 115 } 116 for ( int i = 1; i <= n; ++i) { 117 printf("%d\n",ans[i]); 118 } 119 return 0; 120 }