網上對這題一致好評,然而像我這種沒見過世面的,不知道什麼是好題,什麼題不好......
資料會出現環形依賴關係,環形裡面的軟體選乙個就要全選,相當於一件物品。
所以先跑tarjan,把強連通分量縮成乙個點,之後按強連通分量建圖,原圖 u->v,新邊 scc[v]->scc[u],表示安裝scc[v]以後才能裝scc[u]。
之後是樹形揹包。
這是我的第一道樹形揹包。(我的題解順序不代表寫題順序,我的題解是補得)
很沒有經驗。
第一次是按我自己簡單的思路走的,只得了30。
原因是在子樹空間分配上出了問題,導致在我的dfs過程中丟失了很多狀態。
f[u][j] 表示給以 u 為根的子樹分配 j 空間的最優值。
要列舉每乙個狀態。
第一維要列舉 j,第二維列舉 k,意義在於:當以 u 為根的子樹有 j 空間時,給 u 的子樹 v 分配 j-k 空間。
f[u][j] = max ( f[u][j] , f[u][k] + f[v][j-k] )
上述過程並沒有把根節點的貢獻算進去。
所以之後要一邊迴圈把根節點的貢獻算上。
當狀態成立當且僅當 f[u][j] 的 j>=w[u],此時 f[u][j] = f[u-w[u]] + val[u] 。
// q.c#include#include#include#include#include#includeusing namespace std;
const int n=100+10,m=500+10;
int n,m,_weight[n],weight[n],_value[n],value[n],f[n][m],cnt,head[n];
struct edge
}ed[n];
void add_edge(int a,int b)
int dfs_clock,scc_cnt,pre[n],low[n],idx[n],in[n],g[n][n];
stacks;
void find_scc(int u) else if(!idx[e.v])
low[u]=min(low[u],pre[e.v]);
} if(low[u]==pre[u]) }}
void dfs(int u)
for(int j=m;j>=0;j--)
}void input()
}void prepare()
} }for(int i=1;i<=scc_cnt;i++) if(!in[i]) g[0][i]=true;
}int main()
HAOI2010 軟體安裝
現在我們的手頭有n個軟體,對於乙個軟體i,它要占用wi的磁碟空間,它的價值為vi。我們希望從中選擇一些軟體安裝到一台磁碟容量為m計算機上,使得這些軟體的價值盡可能大 即vi的和最大 但是現在有個問題 軟體之間存在依賴關係,即軟體i只有在安裝了軟體j 包括軟體j的直接或間接依賴 的情況下才能正確工作 ...
HAOI2010 軟體安裝
現在我們的手頭有n個軟體,對於乙個軟體i,它要占用wi的磁碟空間,它的價值為vi。我們希望從中選擇一些軟體安裝到一台磁碟容量為m計算機上,使得這些軟體的價值盡可能大 即vi的和最大 但是現在有個問題 軟體之間存在依賴關係,即軟體i只有在安裝了軟體j 包括軟體j的直接或間接依賴 的情況下才能正確工作 ...
HAOI2010 軟體安裝
開始沒有看懂題,以為就是個樹形依賴揹包,打完之後w40,然後才發現它會有還,要用tarjan縮完點後跑揹包,要建立乙個虛擬節點0連線所有的子圖 注意連線的位置 錯誤示範 1 for int i 1 i n i 這樣會導致0連線的不是入度為0的點 或環 2if dsn i 3 正確 1 for int...