码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P2661 信息传递

时间:2018-11-16 00:28:10      阅读:109      评论:0      收藏:0      [点我收藏+]

标签:深度   判断   nbsp   color   ref   org   line   更新   题解   

传送门

一眼就能看出来是个并查集 但是并不会写...

看了一下题解说是并查集求最小环qwq

所以,每次加入第i个小同学,判断如果他要告诉的小同学k最后会告诉他(也就是转回来了),

就说明出现了一个环,这时更新一下最小环;

否则就记一下他要告诉的小同学fa[x](为下一个环做铺垫)

  (如果已经找到环就不记,否则下次有小同学指向这个环的时候就会进入死循环(感谢题解))

因为每个点的出度都是1,所以当某几个点已经形成了一个环的时候,他们就不可能属于别的环了,

也就是说每个点只能属于0(入度 = 0)或1个环,

可以得出当前这个点形成的环一定是它所能形成的最优解(最短的)!

当发现环的时候,在getfa里面用一个depth记录深度(环的长度);

至于注意事项...一开始我写的是

int getfa(int x,int &d) {
    d++;
    if(fa[x] == x)
        return x;
    return fa[x] = getfa(fa[x],d);
}

 

然而wa了,对照题发现最后一句是错的qaq

于是我通过自己写了一堆测试数据才想明白:

因为每次判断都要调用一次getfa函数,所以即使没有找到环,经过的小同学的fa[]也是动态变化的,

这就导致当最后找到环的时候,中间的很多步骤都被跳过了,

并且由于depth每次清零,所以最后得到的depth并不是真正的答案。

解决方案:不改变fa[x] 

  return getfa(fa[x],d);

(其实我感觉把每个点的步数记下来也可以qwq但是没写出来...以后再说吧x)

完整代码:

技术分享图片
#include<cstdio>
#define min(x,y) (x)<(y)?(x):(y)
using namespace std;
int fa[1000005],n,k,dpth,ans = 10000005;
int getfa(int x,int &d) {
    d++;
    if(fa[x] == x)
        return x;
    return getfa(fa[x],d);
}
int main() {
    scanf("%d",&n);
    for(int i = 1; i <= n; i++)
        fa[i] = i;
    for(int i = 1; i <= n; i++) {
        scanf("%d",&k);
     dpth = 0;
        if(getfa(k,dpth) == i) 
            ans = min(ans,dpth);
        else
            fa[i] = k;
    }
    printf("%d",ans);
    return 0;
}
View Code

 

 

 

 

  

 

Luogu P2661 信息传递

标签:深度   判断   nbsp   color   ref   org   line   更新   题解   

原文地址:https://www.cnblogs.com/mogeko/p/9966926.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!