题解 CF1027D 【Mouse Hunt】
这道题原本写了一个很复杂的DFS,然后陷入绝望的调试。
看了一下题解发现自己完全想复杂了。
这里大概就是补充一些题解没有详细解释的代码吧。。。
(小声BB)现在最优解rank4(话说$O2$负优化什么鬼啊)
1 read(n); 2 for(register int i=1;i<=n;++i)read(c[i]); 3 for(register int i=1;i<=n;++i){ 4 read(a[i]); 5 if(a[i]==i){ 6 vis[i]=1; 7 ans+=c[i]; 8 } 9 } 10 for(register int i=1;i<=n;++i){ 11 if(vis[i])continue; 12 for(register int j=i;;j=a[j]){ 13 if(vis[j]){ 14 if(vis[j]==i+1)ans+=find(j); 15 break; 16 } 17 vis[j]=i+1; 18 } 19 } 20 write(ans);
程序主题内容如下。
前面是读入数据没有什么好讲的。
在读入a的时候先判断一下有没有自环,有的话就不用看了直接加上。
然后我们对每一个点都瞎搞搞(其实就是一个DFS)。
我们从这个点开始一直向下跳。如果遇到已经走过的点就说明有环出现了,这个时候根据vis的值决定是不是这一轮跳出的环(由于可能是之前的)。
然后我们在这个环上跑一下求最小值。(为什么只在环上不在链上前面题解讲得很清楚了)
如果不是已经走过的点,那我们还在链上,继续往下跳吧。
find函数如下:
1 inline int find(int s){ 2 int res=c[s]; 3 for(register int i=a[s];;i=a[i]){ 4 if(i==s)return res; 5 else res=min(res,c[i]); 6 } 7 }