zoukankan      html  css  js  c++  java
  • BZOJ2400 Spoj 839 Optimal Marks

    首先发现每一位二进制可以分开来做。

    然后就变成0、1两种数了,考虑最小割。

    设S表示选0,T表示选1,则

    对于确定的点向数字对应的S/T连边,边权inf;然后原来图中有边的,互相连边,边权为1。

    直接最小割即可,最后还要dfs一下来求出每个未确定的数选的是0还是1。

      1 /**************************************************************
      2     Problem: 2400
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:552 ms
      7     Memory:3180 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <algorithm>
     13  
     14 using namespace std;
     15 typedef long long ll;
     16 const int N = 505;
     17 const int M = 2005;
     18 const int Me = 200005;
     19 const int inf = 1e9;
     20  
     21 struct edge {
     22     int x, y;
     23     edge() {}
     24     edge(int _x, int _y) : x(_x), y(_y) {}
     25 } E[M];
     26  
     27 struct edges {
     28     int next, to, f;
     29     edges() {}
     30     edges(int _n, int _t, int _f) : next(_n), to(_t), f(_f) {}
     31 } e[Me];
     32  
     33 int n, m, S, T;
     34 int a[N], del[N];
     35 int tot, first[N];
     36 int d[N], q[N];
     37 ll ans;
     38  
     39 inline int read() {
     40     int x = 0, sgn = 1;
     41     char ch = getchar();
     42     while (ch < '0' || '9' < ch) {
     43         if (ch == '-') sgn = -1;
     44         ch = getchar();
     45     }
     46     while ('0' <= ch && ch <= '9') {
     47         x = x * 10 + ch - '0';
     48         ch = getchar();
     49     }
     50     return sgn * x;
     51 }
     52  
     53 inline void Add_Edges(int x, int y, int f) {
     54     e[++tot] = edges(first[x], y, f), first[x] = tot;
     55     e[++tot] = edges(first[y], x, 0), first[y] = tot;
     56 }
     57  
     58 bool bfs() {
     59     int l, r, x, y;
     60     memset(d, 0, sizeof(d));
     61     d[q[1] = S] = 1;
     62     for (l = r = 1; l != (r + 1) % N; (++l) %= N) 
     63         for (x = first[q[l]]; x; x = e[x].next)
     64             if (!d[y = e[x].to] && e[x].f)
     65                 d[q[(++r) %= N] = y] = d[q[l]] + 1;
     66     return d[T];
     67 }
     68  
     69 int dfs(int p, int lim) {
     70     if (p == T || !lim) return lim;
     71     int x, y, tmp, rest = lim;
     72     for (x = first[p]; x; x = e[x].next) 
     73         if (d[y = e[x].to] == d[p] + 1 && (tmp = min(e[x].f, rest) > 0)) {
     74             rest -= (tmp = dfs(y, tmp));
     75             e[x].f -= tmp, e[x ^ 1].f += tmp;
     76             if (!rest) return lim;
     77         }
     78     if (lim == rest) d[p] = 0;
     79     return lim - rest;
     80 }
     81  
     82 int Dinic() {
     83     int res = 0;
     84     while (bfs())
     85         res += dfs(S, inf);
     86     return res;
     87 }
     88  
     89 void build_graph(int t) {
     90     int i;
     91     tot = 1, memset(first, 0, sizeof(first));
     92     for (i = 1; i <= n; ++i)
     93         if (a[i] >= 0)
     94             if (a[i] & t) Add_Edges(i, T, inf);
     95             else Add_Edges(S, i ,inf);
     96     for (i = 1; i <= m; ++i)
     97         Add_Edges(E[i].x, E[i].y, 1), Add_Edges(E[i].y, E[i].x, 1);
     98 }
     99  
    100 void find(int p) {
    101     int x, y;
    102     d[p] = 1;
    103     for (x = first[p]; x; x = e[x].next)
    104         if (e[x ^ 1].f && !d[y = e[x].to]) find(y);
    105 }
    106  
    107 void calc_val(int t) {
    108     int i;
    109     memset(d, 0, sizeof(d));
    110     find(T);
    111     for (i = 1; i <= n; ++i)
    112         if (d[i]) del[i] += t;
    113 }
    114  
    115 ll calc_ans() {
    116     ll res = 0;
    117     int i;
    118     for (i = 1; i <= n; ++i)
    119         res += a[i] >= 0 ? a[i] : del[i];
    120     return res;
    121 }
    122  
    123 int main() {
    124     int i;
    125     n = read(), m = read();
    126     S = n + 1, T = n + 2;
    127     for (i = 1; i <= n; ++i)
    128         a[i] = read();
    129     for (i = 1; i <= m; ++i)
    130         E[i] = edge(read(), read());
    131     for (i = 0; i <= 30; ++i) {
    132         build_graph(1 << i);
    133         ans += (ll) (1 << i) * Dinic();
    134         calc_val(1 << i);
    135     }
    136     printf("%lld
    %lld
    ", ans, calc_ans());
    137     return 0;
    138 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    bzoj3816 矩阵变换
    bzoj5029 贴小广告
    【BZOJ-1208】宠物收养所 Splay
    【BZOJ-2879】美食节 最小费用最大流 + 动态建图
    【BZOJ-1984】月下“毛景树” 树链剖分
    写在SDOI2016Round1前的To Do List
    BZOJ solve 100 纪念
    BZOJ-1143&&BZOJ-2718 祭祀river&&毕业旅行 最长反链(Floyed传递闭包+二分图匹配)
    【SDOI2009】解题汇总
    BZOJ-1879 Bill的挑战 状态压缩DP
  • 原文地址:https://www.cnblogs.com/rausen/p/4196699.html
Copyright © 2011-2022 走看看