• CodeForces 698B Fix a Tree (并查集应用)


      当时也是想到了并查集,但是有几个地方没有想清楚,所以就不知道怎么写了,比如说如何确定最优的问题。赛后看了一下别人的思路,才知道自己确实经验不足,思维也没跟上。

      其实没有那么复杂,这个题目我们的操作只有三个 1、确定根节点。2、解环。 3连接子树。

      如果题目中给出了一个或者多个根节点,我们任选一个即可,证明:假设有k个可行根节点,那么选择一个不动,改动k-1次,每种选择都是这样。但如果题目中没有可选根节点,就不可以随便去选了,首先明确这种情况一定存在了1个或者多个环,我们一定要从环中选取根节点,因为这样只进行了一次操作就破环了环结构而且确定了根节点,如果在环外选择根节点,则改动为根节点需要1步,解环也需要一步,不是最优解!

      为了操作方便,使用并查集寻找环,并将找到第一个环的任意一个节点作为根节点。

      在确定了根节点之后,如果遇到其他可行根节点,直接连接到已确定根节点即可,就是连接子树的操作。

      注意:这个注意是对我自己说的,我犯了一个低级错误,我在判断环的时候居然没有用find判断,而是用fa判断,当时还感觉很困惑,以为合并方式不对,发现了以后才感觉自己真是好久没做过并查集了。。

      代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define N 200020
    int a[N],fa[N];
    int Find(int x)
    {
        return x==fa[x] ? x : fa[x] = Find(fa[x]);
    }
    void unin(int x,int y)
    {
        int fax = Find(x);
        int fay = Find(y);
        fa[fay] = fax;
    }
    int main()
    {
        int root = -1,ans=0,n;
        cin>>n;
        for(int i = 1; i <= n; i++)
        {
            cin>>a[i];
            fa[i] = i;
            if(a[i]==i) root = i;
        }
        for(int i = 1; i <= n; i++)
        {
            if(i == a[i] && a[i] == root) continue;
            else if(a[i] == i && i != root)
            {
                a[i] = root;
                ans++;
                unin(root,i);
            }
            else if(a[i] != i && Find(a[i]) != Find(i))
            {
                unin(a[i],i);
            }
            else if(a[i] != i && Find(a[i]) == Find(i))
            {
                ans++;
                if(root == -1)
                {
                    root = i;
                }
                a[i] = root;
                unin(root,i);
            }
        }
        cout<<ans<<endl;
        for(int i = 1; i <= n; i++)
        {
            if(i==n) cout<<a[i]<<endl;
            else cout<<a[i]<<" ";
        }
        return 0;
    }
  • 相关阅读:
    live555源码研究(三)------UsageEnvironment类
    live555源码研究(二)------TaskScheduler类
    live555源码研究(一)------live555MediaServer的启动过程和基本类图
    (转)视频监控相关文章
    【流媒體】live555—VS2008 下live555编译、使用及测试
    【转】PostgreSQL IP地址访问配置
    red5研究(一):下载,工程建立、oflaDemo安装、demo测试
    SVN服务器的搭建和使用
    【转】linux下cvs配置
    【转】js正则表达式语法
  • 原文地址:https://www.cnblogs.com/jifahu/p/5839708.html
Copyright © 2020-2023  润新知