2020牛客暑期多校训练营(第一场)

/*I题 1 or 2
对于边x,y建立两条边(x, y + n, 1), (y, x + n, 1),在s和i之间建边(s, i, d[i]),在i+n和t之间建边(i + n, t, d[i]),
然后从s到t跑一个最大流,判断是不是等于sum(d[1~n]),如果相等输出Yes,否则输出No
*/
#include<bits/stdc++.h> using namespace std; const int inf = 1 << 30, N = 5e4 + 7, M = 3e5 + 7; int head[N], ver[M], edge[M], nex[M], d[N], cur[N]; int n, m, s, t, tot, maxflow; queue<int> q; void init() { maxflow = 0; tot = 1; memset(head, 0, sizeof(head)); } void add(int x, int y, int z) { ver[++tot] = y, edge[tot] = z, nex[tot] = head[x], head[x] = tot; ver[++tot] = x, edge[tot] = 0, nex[tot] = head[y], head[y] = tot; } bool bfs() { memset(d, 0, sizeof(d)); while (q.size()) q.pop(); q.push(s); d[s] = 1; cur[s] = head[s]; while (q.size()) { int x = q.front(); q.pop(); for (int i = head[x]; i; i = nex[i]) { int y = ver[i]; if (edge[i] && !d[y]) { q.push(y); cur[y] = head[y]; d[y] = d[x] + 1; if (y == t) return true; } } } return false; } int dinic(int x, int flow) { if (x == t) return flow; int rest = flow, k, i; for (i = cur[x]; i && rest; i = nex[i]) { int y = ver[i]; if (edge[i] && d[y] == d[x] + 1) { k = dinic(y, min(rest, edge[i])); if (!k) d[y] = 0; edge[i] -= k; edge[i ^ 1] += k; rest -= k; } } cur[x] = i; return flow - rest; } int main() { while (scanf("%d%d", &n, &m) != EOF) { int p, sum = 0, x, y; s = 2 * n + 1; t = 2 * n + 2; init(); for (int i = 1; i <= n; i++) { scanf("%d", &p); add(s, i, p); add(i + n, t, p); sum += p; } for (int i = 1; i <= m; i++) { scanf("%d%d", &x, &y); add(x, y + n, 1); add(y, x + n, 1); } int flow; while (bfs()) { while ((flow = dinic(s, inf))) maxflow += flow; } if (maxflow == sum) printf("Yes\n"); else printf("No\n"); } return 0; }

 

 

posted @ 2020-07-13 10:54  HighLights  阅读(365)  评论(2)    收藏  举报