• [NOIp2015] 信息传递 题解


    补题计划开始。

    题目描述

    求一个有向图的最小环。该图所有点的出度均为 (1)

    数据范围:(1le nle 2 imes 10^5)

    误区

    被样例误导,以为该图一定是连通的,于是认为整个图只有一个环,然后利用该性质进行解题。

    错误代码很简单,就是找到唯一的环然后计算长度,容易误以为是正解实际只有 (40 ext{pts})

    碰到这种错误就 remake 吧。

    解法

    一个做法是 dfs 染色,这种做法很契合题目的出题意图,我特别想写这种做法但是写挂了。

    考虑并查集求最小环。每一次都要判断两点间是否有边。无边则连上,有边则更新最小环大小。

    如果有两个点祖先节点相同,那么就可以构成一个环,长度为两个点到祖先节点长度之和加 (1)

    代码实现

    要直接在并查集上面改哦。具体的看代码。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 200005;
    const int inf = 0x7fffffff;
    
    int n, a[maxn];
    int f[maxn], d[maxn];	// f 保存祖先节点,d 保存到其祖先节点的路径长
    int minn = inf;
    
    int find(int x) {
        if (f[x] != x) {
            int last = f[x];
            f[x] = find(f[x]);
            d[x] += d[last];
        }
        return f[x];
    }
    
    void check(int a,int b)
    {
        int x = find(a), y = find(b);
        if (x != y) {
            f[x] = y; 
            d[a] = d[b] + 1;
        } else 
            minn = min(minn, d[a] + d[b] + 1); 
        return;
    }
    
    int main() {
        cin >> n;
        for(int i = 1; i <= n; i ++) 
            f[i] = i;
        for(int i = 1; i <= n; i ++) {
            int t;
            cin >> t;
            check(i, t); 
        }
        cout << minn << endl;
    }
    
  • 相关阅读:
    sizeof运算符介绍以及常见的坑
    程序员面试需要带身份证和毕业证原件吗
    CentOS7配置rsync实现文件同步
    CentOS7配置samba共享文件系统
    freecplus框架-字符串操作
    freecplus框架-文件操作
    freecplus框架-日志文件操作
    freecplus框架-日期、时间和计时器
    Unix 网络编程卷一源码编译踩坑记录 ubtutu 19.10
    实时人流量监测——海康威视sdk初体验
  • 原文地址:https://www.cnblogs.com/Inversentropir-36/p/15164727.html
Copyright © 2020-2023  润新知