poj 3160 (强连通缩点&简单dp)

来源:互联网 发布:suse centos 区别 编辑:程序博客网 时间:2024/04/29 09:03

Flymouse从武汉大学ACM集训队退役后,做起了志愿者,在圣诞节来临时,Flymouse要打扮成圣诞老人给集训队员发放礼物。集训队员住在校园宿舍的不同寝室,为了节省体力,Flymouse决定从某一个寝室出发,沿着有向路一个接一个的访问寝室并顺便发放礼物,直至能到达的所有寝室走遍为止。对于每一个寝室他可以经过无数次但是只能进入一次,进入房间会得到一个数值(数值可正可负),他想知道他能获得最大的数值和。




#include<cstdio>#include<cstring>#include<vector>#include<stack>#include<algorithm>using namespace std;const int maxn = 30000+10;const int maxm = 150000+10;int n,m;struct node{    int to;    int next;    node(){}    node(int a,int b):to(a),next(b){}}edge[maxm];int head[maxn],low[maxn],dfn[maxn],vis[maxn],clo[maxn],dp[maxn],w[maxn],val[maxn];int tot,cnt,ti;stack<int>s;vector<int>G[maxn];void add_edge(int a,int b){    edge[tot] = node(b,head[a]);    head[a] = tot++;}void tarjan(int u){    s.push(u); dfn[u] = ++ti; low[u] = ti; vis[u] = 1;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v = edge[i].to;        if(!dfn[v])        {            tarjan(v);            low[u] = min(low[u],low[v]);        }        else if(vis[v]==1)            low[u] = min(low[u],dfn[v]);    }    if(low[u]==dfn[u])    {        int y; cnt++;        do{            y = s.top(); s.pop();            vis[y] = 2; clo[y] = cnt;        }while(y!=u);    }}int dfs(int u){    if(dp[u]!=-1) return dp[u];    int len = G[u].size();    int ret = 0;    for(int i=0;i<len;i++)    {        int v = G[u][i];        ret = max(ret,dfs(v));    }    return dp[u] = ret+w[u];}int main(){    int u,v;    while(scanf("%d%d",&n,&m)!=EOF)    {        for(int i=0;i<n;i++){ scanf("%d",&val[i]);}        memset(head,-1,sizeof(head)); tot = 0;        for(int i=0;i<m;i++)        {            scanf("%d%d",&u,&v);            add_edge(u,v);        }        memset(dfn,0,sizeof(dfn));        memset(low,0,sizeof(low));        memset(vis,0,sizeof(vis));        memset(w,0,sizeof(w));        cnt = 0; ti = 0;        for(int i=0;i<n;i++) if(!dfn[i]) tarjan(i);        for(int i=0;i<=cnt+1;i++) G[i].clear();        for(int i=0;i<n;i++) if(val[i]>0) w[clo[i]] += val[i];        for(int i=0;i<n;i++)        {            for(int j=head[i];j!=-1;j=edge[j].next)            {                int v = edge[j].to;                if(clo[i]!=clo[v])                {                    G[clo[i]].push_back(clo[v]);                }            }        }        int ans = 0; memset(dp,-1,sizeof(dp));        for(int i=1;i<=cnt;i++) ans = max(ans,dfs(i));        printf("%d\n",ans);    }    return 0;}


原创粉丝点击