首页 > 其他 > 详细

Codeforces Round #188 (Div. 1) C. Balance

时间:2020-02-01 19:22:45      阅读:67      评论:0      收藏:0      [点我收藏+]


首先,一个联通块里的 $a$ 之和与 $b$ 之和必须相等才有可能,然后就暴力枚举两个点,将 $a>b$ 的找一条路引向 $a<b$ 的,本来以为可以类似于拓扑排序的,就找叶子节点,但发现没办法,因为有可能没法满足最大流量要小于一个值的要求。

技术分享图片
#include <bits/stdc++.h>

const int N = 305;
const int ME = 2 * 5e4 + 7;
const int M = 2 * N * N;

struct E {
  int v, ne;
} e[ME];
int head[N], cnt = 1, n, v, m;

void add(int u, int v) {
  e[++cnt].v = v; e[cnt].ne = head[u]; head[u] = cnt;
}

int color[N], colorNum;
long long sa[N], sb[N];
int a[N], b[N];

void dfs(int u, int colorIndex) {
  color[u] = colorIndex;
  sa[colorIndex] += a[u];
  sb[colorIndex] += b[u];
  for (int i = head[u]; i; i = e[i].ne) {
    int v = e[i].v;
    if (!color[v])
      dfs(v, colorIndex);
  }
}

bool col() {
  for (int i = 1; i <= n; i++)
    if (!color[i]) dfs(i, ++colorNum);
  for (int i = 1; i <= colorNum; i++)
    if (sa[i] != sb[i]) return 0;
  return 1;
}

int res, ans[M][3], pre[N];
bool vis[N];

void findpath(int st, int ed) {
  std::queue<int> que;
  pre[st] = 0;
  que.push(st);
  memset(vis, 0, sizeof(vis));
  while (!que.empty()) {
    int u = que.front(); que.pop();
    vis[u] = 1;
    if (u == ed) return;
    for (int i = head[u]; i; i = e[i].ne) {
      int v = e[i].v;
      if (vis[v]) continue;
      pre[v] = u;
      que.push(v);
    }
  }
}

void solve(int st, int ed, int need) {
  if (st == ed) return;
  int can = std::min(a[pre[ed]], need);
  ans[res][0] = pre[ed], ans[res][1] = ed, ans[res][2] = can;
  if (can) {
    res++;
    a[pre[ed]] -= can;
    a[ed] += can;
  }
  solve(st, pre[ed], need);
  if (can < need) {
    can = need - can;
    ans[res][0] = pre[ed], ans[res][1] = ed, ans[res][2] = can;
    res++;
    a[pre[ed]] -= can;
    a[ed] += can;
  }
}

int main() {
  scanf("%d%d%d", &n, &v, &m);
  for (int i = 1; i <= n; i++)
    scanf("%d", a + i);
  for (int i = 1; i <= n; i++)
    scanf("%d", b + i);
  for (int i = 1, x, y; i <= m; i++) {
    scanf("%d%d", &x, &y);
    add(x, y); add(y, x);
  }
  if (!col()) {
    puts("NO");
    return 0;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = i + 1; j <= n && a[i] != b[i]; j++) {
      if (color[i] != color[j]) continue;
      if (a[i] > b[i] && a[j] < b[j]) {
        findpath(i, j);
        solve(i, j, std::min(a[i] - b[i], b[j] - a[j]));
      } else if (a[i] < b[i] && a[j] > b[j]) {
        findpath(j, i);
        solve(j, i, std::min(a[j] - b[j], b[i] - a[i]));
      }
    }
  }
  printf("%d\n", res);
  for (int i = 0; i < res; i++)
    printf("%d %d %d\n", ans[i][0], ans[i][1], ans[i][2]);
  return 0;
}
View Code

 

Codeforces Round #188 (Div. 1) C. Balance

原文:https://www.cnblogs.com/Mrzdtz220/p/12249126.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!