BZOJ 1589 采集糖果

Posted on 2016-09-01 21:00  ziliuziliu  阅读(187)  评论(0编辑  收藏  举报

23333怎么调了一晚上。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 100500
#define maxe 100500
using namespace std;
struct edge
{
    int v,nxt;
}e[maxe];
int n,xx[maxv],g[maxv],nume=0,dfn[maxv],low[maxv],times=0,stack[maxv],top=0,dp[maxv],ret=0,hash[maxv];
bool vis[maxv];
void addedge(int u,int v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void tarjan(int x)
{
    vis[x]=true;dfn[x]=low[x]=++times;stack[++top]=x;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (!vis[v])
        {
            tarjan(v);
            low[x]=min(low[x],low[v]);
        }
        else low[x]=min(low[x],dfn[v]);
    }
    if (dfn[x]==low[x])
    {
        int p=top,cnt=0;ret++;
        while (dfn[stack[p]]!=low[stack[p]])
        {
            cnt++;
            p--;
        }
        cnt++;
        while (dfn[stack[top]]!=low[stack[top]])
        {
            hash[stack[top]]=ret;
            if (cnt!=1) dp[stack[top]]=cnt;
            top--;
        }    
        hash[stack[top]]=ret;
        if (cnt!=1) dp[stack[top]]=cnt;
        top--;
    }
}
int find(int x)
{
    if (dp[x]) return dp[x];
    else if (xx[x]==x) {dp[x]=1;return 1;}
    else return dp[x]=find(xx[x])+1;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&xx[i]);
        if (i!=xx[i])
            addedge(i,xx[i]);
    }
    for (int i=1;i<=n;i++)
    {
        if (!vis[i])
            tarjan(i);
    }
    for (int i=1;i<=n;i++)
    {
        if (i==xx[i])
        {
            dp[i]=1;
            printf("1\n");
        }
        else printf("%d\n",find(i));
    }
    return 0;
}