BZOJ 2427 HAOI 2010 软件安装 Tarjan+树上DP

来源:互联网 发布:java array排序 编辑:程序博客网 时间:2024/06/07 05:23

题目大意:给出一个每个点都有一个依赖节点的图,选择一个节点必须选择这个节点的依赖节点,才会得到这个节点的权值。每个点有一个空间,给出总空间限制,问最多可以获得多少权值。


思路:出现在一个环中的点要么全选,要么全不选,所以可以先缩点,之后变成一棵树,在树上做一下树上背包就行了。


CODE:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAX 2010using namespace std; int head[MAX],total;int next[MAX],aim[MAX]; inline void Add(int x,int y){    next[++total] = head[x];    aim[total] = y;    head[x] = total;} int cost[MAX],val[MAX];int father[MAX]; int cnt,all; int dfn[MAX],low[MAX],_clock;int stack[MAX],top;bool in_stack[MAX];int changed[MAX],scc; void Tarjan(int x){    dfn[x] = low[x] = ++_clock;    stack[++top] = x;    in_stack[x] = true;    for(int i = head[x]; i; i = next[i]) {        if(!dfn[aim[i]])            Tarjan(aim[i]),low[x] = min(low[x],low[aim[i]]);        else if(in_stack[aim[i]])            low[x] = min(low[x],dfn[aim[i]]);    }    if(dfn[x] == low[x]) {        scc++;        int temp;        do {            temp = stack[top--];            in_stack[temp] = false;            changed[temp] = scc;        }while(temp != x);    }} struct Graph{    int head[MAX],total;    int next[MAX],aim[MAX];         int _in[MAX],f[MAX][MAX];    int cost[MAX],val[MAX];         void Add(int x,int y) {        next[++total] = head[x];        aim[total] = y;        head[x] = total;        ++_in[y];    }    void DP(int x) {        for(int i = head[x]; i; i = next[i]) {            DP(aim[i]);            for(int j = all - cost[x]; j >= 0; --j)                for(int k = 0; k <= j; ++k)                    f[x][j] = max(f[x][j],f[x][k] + f[aim[i]][j - k]);        }        for(int i = all; i; --i) {            if(i >= cost[x]) f[x][i] = f[x][i - cost[x]] + val[x];            else    f[x][i] = 0;        }    }    int GetAns() {        memset(f,0,sizeof(f));        int S = 0;        for(int i = 1; i <= scc; ++i)            if(!_in[i])                Add(S,i);        DP(S);        return f[S][all];    }}graph; int main(){    cin >> cnt >> all;    for(int i = 1; i <= cnt; ++i)        scanf("%d",&cost[i]);    for(int i = 1; i <= cnt; ++i)        scanf("%d",&val[i]);    for(int x,i = 1;i <= cnt; ++i) {        scanf("%d",&x);        if(x)   Add(x,i);    }    for(int i = 1; i <= cnt; ++i)        if(!dfn[i]) Tarjan(i);    for(int x = 1; x <= cnt; ++x)        for(int i = head[x]; i; i = next[i])            if(changed[x] != changed[aim[i]])                graph.Add(changed[x],changed[aim[i]]);    for(int i = 1; i <= cnt; ++i) {        graph.cost[changed[i]] += cost[i];        graph.val[changed[i]] += val[i];    }    cout << graph.GetAns() << endl;    return 0;}


0 0
原创粉丝点击