NBUT 1513 Treasures【tarjan缩点+记忆化搜索】

来源:互联网 发布:ruby精粹专家编程 pdf 编辑:程序博客网 时间:2024/04/30 13:17

转载请注明出处:http://blog.csdn.net/a1dark

分析:这题真心有难度、特别是对于我这种连STL都没掌握的弱菜来说。。。只能全部用临界表存储、毕竟数据太大了、先把SCC缩点、然后一次DFS就过了。。本来想用记忆化搜索的。。但是拙计了。。先就这样做吧快哭了

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn=100005;const int maxm=150005;struct node{    int to,next;}mpt[maxm],map[maxm];int head[maxn];int low[maxn];int dfn[maxn];int vis[maxn];int que[maxn];int belong[maxn];int dp[maxn];int val[maxn];int cnt,index,top,n,m,k,w;void add(int x,int y){    mpt[k].to=y;    mpt[k].next=head[x];    head[x]=k++;}int head1[maxn];void add1(int x,int y){    map[w].to=y;    map[w].next=head1[x];    head1[x]=w++;}void tarjan(int s){    low[s]=dfn[s]=++index;    que[++top]=s;    vis[s]=1;    for(int i=head[s];i!=-1;i=mpt[i].next){        int e=mpt[i].to;        if(!dfn[e]){            tarjan(e);            low[s]=min(low[s],low[e]);        }        else if(vis[e]){            low[s]=min(low[s],dfn[e]);        }    }    if(low[s]==dfn[s]){        cnt++;        int e;        do{            e=que[top--];            belong[e]=cnt;            val[cnt]++;            vis[e]=0;        }while(s!=e);    }}void init(){    memset(head,-1,sizeof(head));    memset(head1,-1,sizeof(head1));    memset(dfn,0,sizeof(dfn));    memset(vis,0,sizeof(vis));    cnt=k=w=index=0;    top=-1;}int start;int maxx;void dfs(int x,int step){    if(step>maxx)maxx=step;    for(int i=head1[x];i!=-1;i=map[i].next){        int s=map[i].to;        dfs(s,step+val[s]);    }}int main(){    int cas=1;    while(scanf("%d%d%d",&n,&m,&start)!=EOF){        int a,b;        init();        memset(belong,-1,sizeof(belong));        memset(val,0,sizeof(val));        for(int i=1;i<=m;i++){            scanf("%d%d",&a,&b);            add(a,b);        }        for(int i=1;i<=n;i++){            if(!dfn[i]){                tarjan(i);            }        }        for(int i=1;i<=n;i++){            int now=i;            for(int j=head[now];j!=-1;j=mpt[j].next){                int s=mpt[j].to;                if(belong[now]!=belong[s]){                    add1(belong[now],belong[s]);                }            }        }        maxx=0;        dfs(belong[start],val[belong[start]]);        printf("Case %d:\n%d\n",cas++,maxx);    }    return 0;}

用记忆化搜索改进了一下:

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn=100005;const int maxm=150005;struct node{    int to,next;}mpt[maxm],map[maxm];int head[maxn];int low[maxn];int dfn[maxn];int vis[maxn];int que[maxn];int belong[maxn];int dp[maxn];int val[maxn];int cnt,index,top,n,m,k,w;void add(int x,int y){    mpt[k].to=y;    mpt[k].next=head[x];    head[x]=k++;}int head1[maxn];void add1(int x,int y){    map[w].to=y;    map[w].next=head1[x];    head1[x]=w++;}void tarjan(int s){    low[s]=dfn[s]=++index;    que[++top]=s;    vis[s]=1;    for(int i=head[s];i!=-1;i=mpt[i].next){        int e=mpt[i].to;        if(!dfn[e]){            tarjan(e);            low[s]=min(low[s],low[e]);        }        else if(vis[e]){            low[s]=min(low[s],dfn[e]);        }    }    if(low[s]==dfn[s]){        cnt++;        int e;        do{            e=que[top--];            belong[e]=cnt;            val[cnt]++;            vis[e]=0;        }while(s!=e);    }}void init(){    memset(head,-1,sizeof(head));    memset(head1,-1,sizeof(head1));    memset(dfn,0,sizeof(dfn));    memset(vis,0,sizeof(vis));    cnt=k=w=index=0;    top=-1;}int start;int maxx;int dfs(int x){    if(dp[x]>val[x])return dp[x];    for(int i=head1[x];i!=-1;i=map[i].next){        int s=map[i].to;        dp[x]=max(dp[x],dfs(s)+val[x]);    }    return dp[x];}int main(){    int cas=1;    while(scanf("%d%d%d",&n,&m,&start)!=EOF){        int a,b;        init();        memset(belong,-1,sizeof(belong));        memset(val,0,sizeof(val));        for(int i=1;i<=m;i++){            scanf("%d%d",&a,&b);            add(a,b);        }        for(int i=1;i<=n;i++){            if(!dfn[i]){                tarjan(i);            }        }        for(int i=1;i<=n;i++){            int now=i;            for(int j=head[now];j!=-1;j=mpt[j].next){                int s=mpt[j].to;                if(belong[now]!=belong[s]){                    add1(belong[now],belong[s]);                }            }        }        for(int i=1;i<=cnt;i++){            dp[i]=val[i];        }        printf("Case %d:\n%d\n",cas++,dfs(belong[start]));    }    return 0;}


原创粉丝点击