SPOJ4882题解
由于SPOJ的服务器过于优异,暴力也给过了。
STL真是个好东西。
主要思路:求出一个点能到达的点集,然后把点集的各个点权值加起来
- 使用STL的bitset记录能到达的点集
- 拓扑排序得到拓扑序列,倒序遍历拓扑序列,更新能到达的点集
#include <cstring>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 20003;
const int maxen = 500003;
int n, m, val[maxn];
int in[maxn], qn, que[maxn];
int head[maxn], las[maxen], to[maxen];
bitset <20003> have[maxn];
void topo() {
qn = 0;
for (int i = 1; i <= n; i++)
if (! in[i]) que[++qn] = i;
for (int i = 1, u, v; i <= qn; i++) {
u = que[i];
for (int j = head[u]; j; j = las[j]) {
v = to[j]; in[v]--;
if (! in[v]) que[++qn] = v;
}
}
}
void solve() {
for (int i = qn, u, v; i >= 1; i--) {
u = que[i];
for (int j = head[u]; j; j = las[j]) {
v = to[j];
have[u] |= have[v];
}
}
for (int i = 1, ans; i <= n; i++) {
ans = 0;
for (int j = 1; j <= n; j++)
if (have[i][j]) ans += val[j];
printf("%d ", ans);
have[i].reset();
}
printf("\n");
}
int main() {
int T; scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &val[i]);
have[i][i] = 1;
}
memset(head, 0, sizeof(head));
for (int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
to[i] = v; las[i] = head[u]; head[u] = i;
in[v]++;
}
topo();
solve();
}
return 0;
}

浙公网安备 33010602011771号