bzoj 1512 [POI2006]Pro-Professor Szu tarjan dp

来源:互联网 发布:rust辅助软件 编辑:程序博客网 时间:2024/06/07 15:21

先tarjan缩点,然后拓扑dp。
似乎有一些细节。。。

#include <bits/stdc++.h>using namespace std;#define N 1000010#define inf 36501int n,m,tot,top,cnt,scc,ans;int head[N],nex[N],to[N];int deep[N],low[N],st[N],bel[N];bool ins[N],vis[N];int du[N],size[N],f[N];vector<int>vec[N];void add(int x,int y){    tot++;    nex[tot]=head[x];head[x]=tot;    to[tot]=y;}void tarjan(int x){    deep[x]=low[x]=++cnt;    st[++top]=x;ins[x]=1;    for(int i=head[x];i;i=nex[i])    {        if(!deep[to[i]])            tarjan(to[i]),low[x]=min(low[x],low[to[i]]);        else if(ins[to[i]])            low[x]=min(low[x],deep[to[i]]);    }    if(deep[x]==low[x])    {        int tmp=st[top--];        ins[tmp]=0;bel[tmp]=++scc;        while(tmp!=x)        {            tmp=st[top--];            ins[tmp]=0;bel[tmp]=scc;        }    }}int main(){    //freopen("tt.in","r",stdin);    scanf("%d%d",&n,&m);n++;    for(int i=1,x,y;i<=m;i++)    {        scanf("%d%d",&x,&y);        add(y,x);        if(x==y)vis[x]=1;    }    for(int i=1;i<=n;i++)        if(!deep[i])tarjan(i);    for(int i=1;i<=n;i++)size[bel[i]]++;    for(int i=1;i<=n;i++)        for(int j=head[i];j;j=nex[j])            if(bel[i]!=bel[to[j]])                vec[bel[i]].push_back(bel[to[j]]),du[bel[to[j]]]++;    for(int i=1;i<=n;i++)        if(vis[i])size[bel[i]]++;    int h=1,r=0;    for(int i=1;i<=n;i++)        if(!du[i])st[++r]=i;    f[bel[n]]=1;    if(size[bel[n]]>1)f[bel[n]]=inf;    while(r>=h)    {        int tmp=st[h++];        for(int i=0,t;i<vec[tmp].size();i++)        {            f[t=vec[tmp][i]]+=f[tmp];            if(f[t]>inf||(size[t]>1&&f[t]))f[t]=inf;            if(--du[t]==0)st[++r]=t;        }    }    for(int i=1;i<n;i++)        ans=max(ans,f[bel[i]]);    if(ans!=inf)printf("%d\n",ans);    else puts("zawsze");    for(int i=1;i<n;i++)        if(f[bel[i]]==ans)            st[++top]=i;    printf("%d\n",top);    for(int i=1;i<=top;i++)        printf("%d ",st[i]);    puts("");    return 0;}
0 0