• Luogu 2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm


    基环树森林,然而我比较菜,直接tarjan找环。

    发现缩点之后变成了DAG,每一个点往下走一定会走到一个环,缩点之后搜一遍看看会走到哪个环以及那个环的编号是多少,答案就是环的$siz$$ + $要走的路程。

    比较垃圾的我忘记了判重边WA了好多发……

    时间复杂度$O(n)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N = 1e5 + 5;
    const int inf = 1 << 30;
    
    int n, to[N], dfsc = 0, dfn[N], low[N], cur[N];
    int scc = 0, siz[N], top = 0, sta[N], bel[N], dis[N];
    int tot = 0, head[N];
    bool vis[N], isCur[N];
    
    struct Edge {
        int to, nxt;
    } e[N];
    
    inline void add(int from, int ver) {
        e[++tot].to = ver;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    inline void read(int &X) {
        X = 0; char ch = 0; int op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline int min(int x, int y) {
        return x > y ? y : x;
    }
    
    inline int max(int x, int y) {
        return x > y ? x : y;
    }
    
    void tarjan(int x) {
        dfn[x] = low[x] = ++dfsc;
        sta[++top] = x, vis[x] = 1;
        
        int y = to[x];
        if(!dfn[y]) {
            tarjan(y);
            low[x] = min(low[x], low[y]);
        } else if(vis[y]) low[x] = min(low[x], dfn[y]);
        
        if(low[x] == dfn[x]) {
            ++scc;
            for(; sta[top + 1] != x; --top) {
                bel[sta[top]] = scc;
                siz[scc]++;
                vis[sta[top]] = 0;
            }
        }
    }
    
    void dfs(int x) {
        vis[x] = 1;
        if(isCur[x]) {
            dis[x] = 0, cur[x] = x;
            return;
        }
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(!vis[y]) dfs(y);
            dis[x] = dis[y] + 1, cur[x] = cur[y];
        }
    }
    
    int main() {
    //    freopen("testdata.in", "r", stdin);
    //    freopen("mine.out", "w", stdout);
        
        read(n);
        for(int i = 1; i <= n; i++) read(to[i]);
        
        for(int i = 1; i <= n; i++)
            if(!dfn[i]) tarjan(i);
            
    /*    for(int i = 1; i <= n; i++)
            printf("%d ", bel[i]);
        printf("
    ");   */
        for(int i = 1; i <= n; i++)
            if(to[i] == i) isCur[bel[i]] = 1;
        for(int i = 1; i <= scc; i++) 
            if(siz[i] >= 2) isCur[i] = 1;
        
        for(int i = 1; i <= n; i++) {
            if(bel[i] == bel[to[i]]) continue;
            add(bel[i], bel[to[i]]);
        }    
        
        for(int i = 1; i <= scc; i++)
            if(!vis[i]) dfs(i);
        
    /*    for(int i = 1; i <= scc; i++)
            printf("%d ", cur[i]);
        printf("
    ");   */
        
        for(int i = 1; i <= n; i++) {
            if(isCur[bel[i]]) printf("%d
    ", siz[bel[i]]);
            else printf("%d
    ", dis[bel[i]] + siz[cur[bel[i]]]);
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    读写csv文件
    安卓跳转
    求时间精确到秒的数
    航空公司客户价值分析
    利用LM神经网络和决策树去分类
    拉格朗日插值法
    ID3
    K最近邻
    贝叶斯分类
    FilterDispatcher已被标注为过时解决办法
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9595345.html
Copyright © 2020-2023  润新知