「Solution」
最大流+拆点
「代码」
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define maxn 20000
#define INF 1 << 30
using namespace std;
struct E
{
int from, to, tab, next;
}edge[maxn];
int dist[maxn], head[maxn], d[maxn], in[maxn], out[maxn], ans, s, t, tot, m, n;
void add_edge(int u, int v, int f)
{
tot++;
edge[tot].from = u, edge[tot].to = v, edge[tot].tab = f, edge[tot].next = head[u], head[u] = tot;
tot++;
edge[tot].from = v, edge[tot].to = u, edge[tot].tab = 0, edge[tot].next = head[v], head[v] = tot;
}
int dfs(int x, int low)
{
int a;
if (x == t) return low;
for (int i = head[x]; i != -1; i = edge[i].next)
if (dist[edge[i].to] == dist[x] + 1 && edge[i].tab > 0 && (a = dfs(edge[i].to, min(low, edge[i].tab))))
{
edge[i].tab -= a, edge[i^1].tab += a;
return a;
}
return 0;
}
int bfs()
{
int l, r, k;
memset(dist, 0xff, sizeof(dist));
dist[s] = 0;
d[0] = 0, d[1] = s;
l = 0, r = 1;
while (l < r)
{
k = d[++l];
for (int i = head[k]; i != -1; i = edge[i].next)
if (edge[i].tab > 0 && dist[edge[i].to] < 0) dist[edge[i].to] = dist[k] + 1, d[++r] = edge[i].to;
}
if (dist[t] > 0) return 1; else return 0;
}
void dinic()
{
ans = 0;
while (bfs()) ans += dfs(s, INF);
}
int main()
{
int x, y, f;
tot = -1;
memset(head,0xff,sizeof(head));
scanf("%d%d", &n, &m);
s = 2 * n + 1, t = 2 * n + 2;
for (int i = 1; i <= n; i++)
{
scanf("%d", &f);
add_edge(i, i+n, f);
}
for (int i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
in[y]++, out[x]++;
add_edge(x+n, y, INF);
}
for (int i = 1; i <= n; i++)
{
if (in[i] == 0) add_edge(s, i, INF);
if (out[i] == 0) add_edge(i+n, t, INF);
}
dinic();
printf("%d\n", ans);
return 0;
}