题解 P5382 【[THUPC2019]改善生活】
首先让我们证明一个结论:存在一个最优解小Z只引出了一个话题
感性理解:我多选了一个相当与把两个答案进行某种意义下的平均,不会变的更优
证明:
若
设当只选
当只选
当选
显然
证毕
所以只要枚举选的点,然后算答案即可(我的代码实现求了个传递闭包)
Talk is cheap, show me the code.
码风丑,请大佬轻喷
#include <bits/stdc++.h>
using namespace std;
int mp[710][710], n, m, c[710], w[710];
int cnt[710], ans;
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", c + i);
for(int i = 1; i <= n; i++) scanf("%d", w + i);
for(int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
mp[u][v] = 1;
}
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) mp[i][j] |= mp[i][k] & mp[k][j];
//没有错,n ^ 3 就是能过700 (700 ^ 3 = 3e8)
for(int i = 1; i <= n; i++) {
if(c[i] == 1) {
memset(cnt, 0, sizeof cnt);
for(int j = 1; j <= n; j++) if(mp[i][j]) cnt[c[j]] += w[j];
for(int j = 2; j <= n; j++) ans = max(ans, cnt[j] / w[i]);
}
}
printf("%d\n", ans);
return 0;
}