



3 5 10 5 4 10 8 1 10 1 3 1 4 1 5 1 3 2 1 2 5 4 3 4 3 4 5 5 1 1 4 4 6 1 9 4 7 2 9 5 10 5 2 8 8 10 10 2 1 2 3 3 2 3 4 3 1 3 2 3 4 4 1 5 4 5 1 1 4 2 3 4 7 3 10 1 5 5 10 5 9 9 8 2 1 1 5 1 5 2 1 2 4 2 4 2 4 3 2 3 1 4 3 4 3 5 9 3 9 2 7 5 1 5 4

40 60 90 70 90 8 30 70 100 10 9 81 63 1
4
这道题总体来说比较好做,开始考试十分钟后就想出了做法。但是,,,,,,写完后有一个变量(num)忘清空了,就此丢了30分。
做法————tarjan缩点+拓扑dp。
另外,神仙rqy用BFS把标程踩了。
上我的代码
额,忘了保存,它没了,只能贴一下老师的了
#include <cstdio>
#include <cstring>
template <class cls>
inline cls min(const cls & a, const cls & b) {
return a < b ? a : b;
}
template <class cls>
inline cls max(const cls & a, const cls & b) {
return a > b ? a : b;
}
const int mxn = 200005;
const int mxm = 400005;
int n, m, k, w[mxn];
struct edge {
int u, v;
} edges[mxm];
int tot;
int hd[mxn];
int to[mxm << 1];
int nt[mxm << 1];
inline void add_edge(int u, int v) {
nt[++tot] = hd[u];
to[tot] = v;
hd[u] = tot;
}
int tim;
int cnt;
int top;
int dfn[mxn];
int low[mxn];
int stk[mxn];
int scc[mxn];
void tarjan(int u) {
dfn[u] = low[u] = ++tim; stk[++top] = u;
for (int e = hd[u], v; e; e = nt[e])
if (v = to[e], scc[v] == 0) {
if (dfn[v] == 0)tarjan(v),
low[u] = min(low[u], low[v]);
else
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
cnt += 1;
do {
scc[stk[top]] = cnt;
} while (stk[top--] != u);
}
}
int oe[mxn];
int mx[mxn];
int que[mxn];
void bfs() {
int l = 0, r = 0;
for (int i = 1; i <= cnt; ++i)
if (oe[i] == 0)
que[r++] = i;
while (l < r) {
int u = que[l++];
for (int e = hd[u], v; e; e = nt[e])
if (v = to[e], mx[v] = max(mx[v], mx[u]), --oe[v] == 0)
que[r++] = v;
}
}
int main() {
int cas;
scanf("%d", &cas);
for (int c = 0; c < cas; ++c) {
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; ++i)
scanf("%d", w + i);
memset(hd, 0, sizeof(int) * (n + 5)); tot = 0;
for (int i = 0; i < m; ++i) {
scanf("%d%d", &edges[i].u, &edges[i].v);
add_edge(edges[i].u, edges[i].v);
}
tim = cnt = top = 0;
memset(scc, 0, sizeof(int) * (n + 5));
memset(dfn, 0, sizeof(int) * (n + 5));
for (int i = 1; i <= n; ++i)
if (scc[i] == 0)
tarjan(i);
memset(hd, 0, sizeof(int) * (cnt + 5)); tot = 0;
memset(oe, 0, sizeof(int) * (cnt + 5));
memset(mx, 0, sizeof(int) * (cnt + 5));
for (int i = 0; i < m; ++i) {
int u = scc[edges[i].u];
int v = scc[edges[i].v];
if (u != v)
add_edge(v, u), oe[u] += 1;
}
for (int i = 1; i <= n; ++i)
mx[scc[i]] = max(mx[scc[i]], w[i]);
bfs();
for (int i = 0, u, x; i < k; ++i) {
scanf("%d%d", &u, &x);
printf("%lld
", 1LL * x * mx[scc[u]]);
}
}
return 0;
}