現在我們的手頭有n個軟體,對於乙個軟體i,它要占用wi的磁碟空間,它的價值為vi。我們希望從中選擇一些軟體安裝到一台磁碟容量為m計算機上,使得這些軟體的價值盡可能大(即vi的和最大)。
但是現在有個問題:軟體之間存在依賴關係,即軟體i只有在安裝了軟體j(包括軟體j的直接或間接依賴)的情況下才能正確工作(軟體i依賴軟體j)。幸運的是,乙個軟體最多依賴另外乙個軟體。如果乙個軟體不能正常工作,那麼它能夠發揮的作用為0。
我們現在知道了軟體之間的依賴關係:軟體i依賴軟體di。現在請你設計出一種方案,安裝價值盡量大的軟體。乙個軟體只能被安裝一次,如果乙個軟體沒有依賴則di=0,這時只要這個軟體安裝了,它就能正常工作。
第1行:n, m (0<=n<=100, 0<=m<=500)
第2行:w1, w2, … wi, …, wn (0<=wi<=m )
第3行:v1, v2, …, vi, …, vn (0<=vi<=1000 )
第4行:d1, d2, …, di, …, dn (0<=di<=n, di≠i )
乙個整數,代表最大價值。
3 10
5 5 6
2 3 4
0 1 1
根據題意,很容易想到金明的預算方案這道題,然後你就跪了,軟體可以無限制地向上依賴,並不是主附件關係。
然後你就想到了樹形揹包,然後就得了40分(我就是這樣的),因為軟體可以互相依賴,a依賴b,b依賴a,要麼全部選,要麼全部不選,因此可以進行tarjan縮點。
然後就陷入無限除錯狀態。
再見
#include#include#include#include#include#include#include#include#includeusing namespace std;
inline const
int get_int()
while(x>='0'&&x<='9')
return num*bj;
}int head[5005],treehead[5005],indegree[5005],cnt=0,cnt2=0;
struct edge edge[5005],tree[5005];
struct software a[5005],new[5005];
void addedge(int from,int
to)
void addnewedge(int from,int
to)
intstep=0,dfn[5005],lowlink[5005],stack[5005],top=0,instack[5005],belong[5005],scc=0;
void tarjan(int
now) else
if(instack[next])lowlink[now]=min(lowlink[now],dfn[next]);
}if(lowlink[now]==dfn[now]) while(y!=now);
}}int n,size,map[505][505],f[505][505];
void treedp(int
now)
}int main()
for(int i=1; i<=n; i++)if(!dfn[i])tarjan(i);
for(int
now=1; now
<=n; now++)
for(int i=head[now]; i; i=edge[i].next)
}for(int i=1; i<=scc; i++)
if(indegree[i]==0)addnewedge(scc+1,i);
scc++;
treedp(scc);
printf("%d\n",f[scc][size]);
return 0;
}
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...
HAOI2010 軟體安裝
傳送門 一開始我以為這道題是乙個比較正常的分組揹包,只不過原來做的題目的限制條件是數目,這次是有體積 軟體所佔空間 的限制,但是兩者好像沒什麼差異 於是我就仿著正常的分組揹包寫了一下,然後過了樣例。我才不會告訴你我一開始結果全是0,因為我寫錯了 交上去一看只有10分 回來發現原來這題並沒有說是一棵樹...