zoukankan      html  css  js  c++  java
  • P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm

    对于一个牛,它存在两种状态:1.处于联通分量 2.不处于联通分量。对于处于联通分量的牛,求出联通分量的大小;对于不处于联通分量的牛,求出其距离联通分量的路程+联通分量大小。

    不同的联通分量,染上不同的颜色,可以计算各个联通分量的大小。

    #include<bits/stdc++.h>
    using namespace std;
    
    int vis[100005];
    int low[100005];
    int Loop[100005],color[100005],dfn[100005],head[100005],ans[100005],st[100005], Next[100005];
    int pos;
    int k=1;
    int col;
    int top;
    
    struct node
    {
        int v,next;
    }edge[100005];
    
    void Add(int u,int v)
    {
        edge[k].v = v;
        edge[k].next = head[u];
        head[u] = k++;
    }
    
    void Find(int root,int x,int step)
    {
        if(ans[x]!=0)
        {
            ans[root] = ans[x]+step;
            return;
        }
        else
            Find(root,Next[x],step+1);
    }
    
    void Tarjan(int u)
    {
        dfn[u] = low[u] = ++pos;
        st[++top] = u;
        vis[u] = 1;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v = edge[i].v;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u] = min(low[u],low[v]);
            }
            else if(vis[v])
            {
                low[u] = min(low[u],dfn[v]);
            }
        }
        if(dfn[u] == low[u])
        {
            col++;
            int x;
            do{
                x = st[top--];
                vis[x] = 0;
                color[x] = col;
            }while(x!=u);
        }
    }
    
    int main()
    {
        memset(head,-1,sizeof(head));
        int n,v;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&v);
            Next[i] = v;
            Add(i,v);
            if(v==i)
                ans[i] = 1;
        }
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i])
            {
                Tarjan(i);
            }
        }
        for(int i=1;i<=n;i++)
        {
            Loop[color[i]]++;
        }
        for(int i=1;i<=n;i++)
        {
            if(Loop[color[i]]!=1)
                ans[i] = Loop[color[i]];
        }
        for(int i=1;i<=n;i++)
        {
            if(ans[i]==0)
                Find(i,Next[i],1);
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/alan-W/p/10756744.html
Copyright © 2011-2022 走看看