BZOJ3037: 创世纪

来源:互联网 发布:mac蓝牙连接iphone 编辑:程序博客网 时间:2024/05/17 07:05

WA了好几拨
发现自己好傻以前还是会打仙人掌的现在连外向基环树都不会打了。。
注意分一下类 关于取还是不取的

#include<cstdio>#include<cmath>#include<cstdlib>#include<iostream>using namespace std;int n;bool check[1000001];int f[1000001],g[1000001];int cnt;int tot;int F[1000001],visit[1000001];int root;int father(int u){while(!visit[u])visit[u]=true,u=F[u];root=u;}struct Chain{    int u;    Chain *next;    Chain(){next=NULL;}}*Head[1000001];inline void addside(int a,int b){    Chain *tp=new Chain;    tp->next=Head[a];    Head[a]=tp;tp->u=b;}const   int INF=1<<25;char c;inline void read(int &a){    a=0;do c=getchar();while(c<'0'||c>'9');    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}bool done[1000001];int flag[1000001];bool can;void DFS(int u){    done[u]=true;    if(flag[u])f[u]=-INF;    else f[u]=1;    g[u]=0;    int maxg=INF;    for(Chain *tp=Head[u];tp;tp=tp->next)     if(tp->u!=root)       {          DFS(tp->u);          g[u]+=max(f[tp->u],g[tp->u]);          f[u]+=max(f[tp->u],g[tp->u]);          if(f[tp->u]<g[tp->u])maxg=0;          else             maxg=min(maxg,f[tp->u]-g[tp->u]);       }            else if(flag[tp->u])             maxg=0;        f[u]-=maxg;}int main(){    int i;    freopen("std.in","r",stdin);    freopen("self.out","w",stdout);    read(n);    for(i=1;i<=n;i++)         read(F[i]),addside(F[i],i);    int tp,ans=0;    for(i=1;i<=n;i++)      if(!done[i])       {        can=false;         father(i);         DFS(root);         tp=max(f[root],g[root]);         flag[root]=true;         DFS(root);         tp=max(g[root],tp);         ans+=tp;       }    printf("%d\n",ans);    return 0;}
0 0