zoukankan      html  css  js  c++  java
  • codeforces 434D

    题意:有n<=50个点,每个点有xi有[li, ri]种取值,-100 <= li <= ri <= 100,并且给定m<=100条边,每条边为u,v,d表示xu<=xv+d。

            每个点value fi(x) = ai*x^2 + bi*x + ci。现在求一种合法的方案,使得权值和最大。

    思路:先不考虑的xu<=xv + d。那么建图:

           首先考虑到每个点的权值可能为负,并且求最大与最小割相反,

            所以先 取反再+oo(一个很大的数),最后再减掉即可

            对于每个点,拆成ri-li+1个点,

            对于第k个点,node(k, i)表示第k个点值为i对应的标号

            值为i-1跟i连一条边<node(k, i-1), node(k, i),  oo - f(k, i)>的边,

            S到第一个点连<S, node(k, l[k]), f(k, l[k])>

           最后一个点到T连<node(k,r[k]), Inf>

           那么很明显n*oo-最小割就是答案。。

           但是如果有了限制条件xu<=xv + d,我们怎么把限制条件加到图上呢?

           对于一对关系,xu<=xv+d

           考虑到点u,如果node(u, i)到node(u,i+1)之间的边在割集里,那么说明xu=i+1

           也就是说如果xv<xu-d是非法的,也就是说对于v在xu-d之前出现割是非法的。

           那么我们可以连<node(u,i), node(v, i-d), Inf>的边,使得方案合法。。

    code:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define M0(a) memset(a, 0, sizeof(a))
     4 #define Inf 0x3fffffff
     5 const int maxn = 20010;
     6 const int maxm = 900010;
     7 const int big = 15000000;
     8 struct oo{
     9     int y, f, next;
    10 };
    11 struct MaxFlow{
    12        int n, S, T, tot;
    13        int son[maxn], dist[maxn], gap[maxn];
    14        oo e[maxm];
    15        int sap(int x, int aug){
    16            if (x == T) return aug;
    17            int mind = n;
    18            int sum = 0, f;
    19            for (int p = son[x]; p != -1; p = e[p].next){
    20                   int y = e[p].y;
    21                   if (dist[y] + 1 == dist[x] && e[p].f){
    22                        f = sap(y, min(e[p].f, aug - sum));
    23                        e[p].f -= f;
    24                        e[p^1].f += f;
    25                        sum += f;
    26                        if (sum == aug || dist[S] >= n) return sum;
    27                   }
    28                   if (e[p].f) mind = min(mind, dist[y]);
    29            }
    30            if (!sum){
    31                if (!(--gap[dist[x]])) dist[S] = n;
    32                ++gap[dist[x] = mind + 1];
    33            }
    34            return sum;
    35        }
    36        void add(int x, int y, int f){
    37             e[tot].y = y; e[tot].f = f;
    38             e[tot].next = son[x]; son[x] = tot++;
    39             e[tot].y = x; e[tot].f = 0;
    40             e[tot].next = son[y]; son[y] = tot++;
    41        }
    42 
    43        void init(int S, int T, int n){
    44             memset(son, -1, sizeof(son));
    45             tot = 0;
    46             this->S = S, this->T = T, this->n = n;
    47        }
    48        int maxflow(){
    49             M0(gap);
    50             M0(dist);
    51             gap[0] = n;
    52             int ans = 0;
    53             while (dist[S] < n) ans += sap(S, Inf);
    54             return ans;
    55        }
    56 } F;
    57 int S, T;
    58 int n, m, a[120], b[200], c[200], l[200], r[200];
    59 inline int f(const int&k, const int& x){
    60      return big - (a[k] * x * x + b[k] * x + c[k]);
    61 }
    62 
    63 inline int node(const int&k, const int& x){
    64      return x == l[k] - 1 ? S : (k-1) * 201 + x + 101;
    65 }
    66 
    67 void solve(){
    68      for (int i = 1; i <= n; ++i) scanf("%d%d%d", &a[i], &b[i], &c[i]);
    69      for (int i = 1;  i<= n; ++i) scanf("%d%d", &l[i], &r[i]);
    70      S = 0, T = 201 * n + 1;
    71      F.init(S, T, T + 1);
    72      for (int i = 1; i <= n; ++i){
    73          for (int j = l[i]; j <= r[i]; ++j)
    74              F.add(node(i, j-1), node(i, j), f(i, j));
    75          F.add(node(i, r[i]), T, Inf);
    76      }
    77      int u, v, d;
    78      int x;
    79      for (int i = 1; i <= m; ++i){
    80           scanf("%d%d%d", &u, &v, &d);
    81           for (int j = l[v]; j <= r[v]; ++j) if (j + d <= r[u]){
    82                   x = j + d;
    83                   if (x < l[u]) x = l[u] -1;
    84                   F.add(node(u, x), node(v, j), Inf); 
    85           }
    86      }
    87      int ans = big * n;
    88      ans -= F.maxflow();
    89      cout << ans << endl;
    90 }
    91 
    92 int main(){
    93 //    freopen("a.in", "r", stdin);
    94     while (scanf("%d%d", &n, &m) != EOF){
    95         solve();
    96     }            
    97 }
    View Code
  • 相关阅读:
    Linq分组后,再对分组后的每组数据进行排序,获取每组的第一条记录
    C/C++ 常量存储: 总结
    张庆科(山师大硕导简介) [转载]
    composer [packagist]包制作(入门篇)
    MMGCN: Multi-modal Graph Convolution Network for Personalized Recommendation of Micro-video
    opencv.js编译
    推荐
    推荐
    推荐
    Azure Automation (10) 在Automation中动态修改Azure Analysis Firewall防火墙规则
  • 原文地址:https://www.cnblogs.com/yzcstc/p/4062097.html
Copyright © 2011-2022 走看看