poj 3160 Father Christmas flymouse

http://poj.org/problem?id=3160

题意:给出一个有向图,每个点有一个点权,点权可能是正也可能为负,一个人从某点出发,沿着一些路,访问结点,或者仅仅是路过这个结点,而不去访问,最后求他能访问到的最大的点权和。

思路:在有向图里,经过一个点,可以访问,也可以不访问,所以可以把环上的值都取完,其它的能达到就取。因此先进行缩点聚值,然后dfs+记忆化求最大值。

View Code
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<bitset>
#include<string>
#include<climits>
#include<cstdio>
#include<vector>
#include<utility>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define IN puts("in")
#define OUT puts("out")
#define FR(x) freopen(x,"r",stdin)
#define FW(x) freopen(x,"w",stdout)
#define MSET(x,y) memset(x,y,sizeof(x))
#define ST system("pause")
using namespace std;

const int maxn = 30005;

struct nd
{
        int u,v,next;
}edge[maxn*5];

int head[maxn],vis[maxn],dfn[maxn],low[maxn],val[maxn],belong[maxn],c[maxn],st[maxn],in[maxn],hash[maxn];
int ecnt,cnt,idx,tp,ans;

void add(int u,int v)
{
        edge[ecnt].u = u;
        edge[ecnt].v = v;
        edge[ecnt].next = head[u];
        head[u] = ecnt++;
}
void tarjan(int u)
{
        int i,v;
        dfn[u] = low[u] = ++idx;
        vis[u] = 1;
        st[++tp] = u;
        for(i = head[u]; i != -1; i = edge[i].next)
        {
                v = edge[i].v;
                if(!dfn[v]){
                        tarjan(v);
                        low[u] = min(low[v],low[u]);
                }else if(vis[v]) low[u] = min(dfn[v],low[u]);
        }
        if(low[u]==dfn[u])
        {
                ++cnt;
                do{
                        v = st[tp--];
                        vis[v] = 0;
                        belong[v] = cnt;
                        c[cnt] += val[v];
                }while(v!=u);
        }
}
void dfs(int u,int sum)
{
        int i,v;
        if(sum<=hash[u])return ;
        hash[u] = sum;
        ans = max(ans,sum);
        for(i = head[u]; i != -1; i = edge[i].next)
                dfs(edge[i].v,sum+c[edge[i].v]);
}
void processing()
{
        int i,j,k,t,n,m,u,v;
        while(scanf("%d %d",&n,&m)==2)
        {
                for(i = 0; i < n; ++ i){scanf("%d",val+i);if(val[i]<0)val[i]=0;}
                MSET(c,0);
                MSET(belong,0);
                MSET(dfn,0);
                MSET(in,0);
                MSET(low,0);
                MSET(vis,0);
                MSET(head,-1);
                ecnt = cnt = idx = tp = 0;
                for(i = 0; i < m; ++ i)
                {
                        scanf("%d %d",&u,&v);
                        add(u,v);
                }
                for(i = 0; i < n; ++ i)if(!dfn[i])tarjan(i);
                k = ecnt; ecnt = 0;
                MSET(head,-1);
                for(i = 0; i < k; ++ i)
                {
                        u = belong[edge[i].u];
                        v = belong[edge[i].v];
                        if(v!=u){add(u,v);in[v]++;}
                }
                ans = 0;
                MSET(hash,-1);
                for(i = 1; i <= cnt; ++ i) if(!in[i])dfs(i,c[i]);
                printf("%d\n",ans);
        }
}

int main()
{
        processing();
        return 0;
}

posted on 2012-07-04 11:16  aigoruan  阅读(176)  评论(0)    收藏  举报

导航