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
  • 相关阅读:
    day12_函数
    day12_游标
    day12_序列——重置序列
    day12_序列——oracle主键自动增加
    day12_B2B用户禁止PLSQL登录
    七月未央,安之若素
    php----显示中文乱码的问题
    C#--中实现邮件发送
    C#--使用存储过程
    C#--之文件操作
  • 原文地址:https://www.cnblogs.com/alan-W/p/10756744.html
Copyright © 2011-2022 走看看