bzoj1589 [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果(tarjan缩点+记忆化搜索)

先tarjan缩点,然后记忆化搜索。。每个点就一个出度,重建图后一个强连通若是大于1则不可能有出度。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define pa pair<int,int>
#define N 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,to[N],to1[N],dfn[N],low[N],dfnum=0,bel[N],sz[N],scc=0,ans[N];
bool inq[N];
stack<int>q;
void tarjan(int x){
    dfn[x]=low[x]=++dfnum;q.push(x);inq[x]=1;
    if(!dfn[to[x]]) tarjan(to[x]),low[x]=min(low[x],low[to[x]]);
    else if(inq[to[x]]) low[x]=min(low[x],dfn[to[x]]);
    if(low[x]==dfn[x]){
        ++scc;while(1){
            int y=q.top();q.pop();inq[y]=0;
            bel[y]=scc;sz[scc]++;if(x==y) break;
        }
    }
}
void rebuild(){
    for(int i=1;i<=n;++i)
        if(bel[i]!=bel[to[i]])
            to1[bel[i]]=bel[to[i]];
}
int solve(int x){
    if(ans[x]) return ans[x];
    ans[x]=sz[x];
    if(sz[x]==1&&to1[x]) ans[x]+=solve(to1[x]);
    return ans[x];
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();for(int i=1;i<=n;++i) to[i]=read();
    for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
    rebuild();
    for(int i=1;i<=n;++i)
        printf("%d\n",solve(bel[i]));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值