分析
首先有一个结论:存在一个最优解,满足小 Z 只引出了一个话题。
感性理解的话就是如果再引出一个话题的话相当于两个话题取了平均值,答案不会变得更优。
那么直接枚举引出了哪个话题,再直接计算就好了。
注意到题目中要传递闭包,$\mathcal{O}(n^3)$ 做法不够优秀,可以用 bitset
做到 $\mathcal{O}(\frac{n^3}{\omega})$ 。
代码
// ===================================
// author: M_sea
// website: http://m-sea-blog.com/
// ===================================
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cstdio>
#include <cmath>
#define re register
using namespace std;
inline int read() {
int X=0,w=1; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
return X*w;
}
const int N=700+10;
int n,m,ans=0;
int c[N],w[N],cnt[N];
bitset<N> G[N];
int main() {
n=read(),m=read();
for (re int i=1;i<=n;++i) c[i]=read();
for (re int i=1;i<=n;++i) w[i]=read();
for (re int i=1;i<=m;++i) {
int u=read(),v=read();
G[u][v]=1;
}
for (re int i=1;i<=n;++i)
for (re int j=1;j<=n;++j)
if (G[j][i]) G[j]|=G[i];
for (re int i=1;i<=n;++i) {
if (c[i]!=1) continue;
memset(cnt,0,sizeof(cnt));
for (re int j=1;j<=n;++j) if (G[i][j]) cnt[c[j]]+=w[j];
for (re int j=2;j<=n;++j) ans=max(ans,cnt[j]/w[i]);
}
printf("%d\n",ans);
return 0;
}