題意:有n個軟體,有的軟體依賴於某些軟體,求最大空間為m時的最大收益。
題解:容易發現有些軟體互相依賴組成了乙個環。此時這些依賴關係組成的基環樹中,環沒有出邊。所以把環縮成點。此時,森林中除了縮過點的樹以外,根節點都有一條來自虛擬節點0的入邊。因此,我們從0點向每個縮過點的樹連邊,再做一次樹上揹包就行了。
#include
#include
#include
using
namespace std;
const
int maxn =
101;
const
int maxm =
501;
struct edgee[maxn]
;int n, m, w[maxn]
, v[maxn]
;int fir[maxn]
, nxt[maxn <<1]
, to[maxn <<1]
, cnt;
int dfn[maxn]
, low[maxn]
, tim;
int sta[maxn]
, vis[maxn]
, top;
int scc[maxn]
, w[maxn]
, v[maxn]
, size[maxn]
, cont;
int dp[maxn]
[maxm]
;inline
intread()
while
(ch >=
'0'&& ch <=
'9')
return k * f;
}inline
void
add_edge
(int a,
int b)
void
tarjan
(int u)
else
if(vis[v]
) low[u]
=min
(low[u]
, dfn[v]);
}if(dfn[u]
== low[u]
)while
(sta[top +1]
!= u);}
}void
dfs(
int u)}}
if(u)}}
intmain()
for(
int i =
1; i <= n; i++)if
(!dfn[i]
)tarjan
(i);
memset
(fir,-1
,sizeof
(fir)
); cnt =0;
for(
int i =
1; i <= n; i++)if
(scc[e[i]
.fr]
!= scc[e[i]
.to]
)add_edge
(scc[e[i]
.fr]
, scc[e[i]
.to]);
for(
int i =
1; i <= cont; i++)if
(size[i]
>1)
add_edge(0
, i)
;//size大於1的點被縮過
dfs(0)
;printf
("%d"
, dp[0]
[m])
;return0;
}
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...