• BZOJ 3996 [TJOI 2015] 线性代数 解题报告


    首先,我们可以得到:

    $$D = sum_{i=1}^{n}sum_{j=1}^{n}a_i imes a_j imes b_{i,j} - sum_{i=1}^{n}a_i imes c_i$$

    那么是不是就相当于这样的问题:

    有 $n$ 个物品,你可以选择一些物品出来,如果同时选了 $i,j$ 两个物品那么就有 $b_{i,j}$ 的收益,然而每一个物品都有一个代价 $c_i$,求最大收益。

    这是经典的最小割模型:

    • 连边 $S o Dot(i,j)$,流量为 $b_{i,j}$。
    • 连边 $Dot(i,j) o i$ 以及 $Dot(i,j) o j$,流量为 $infty$。
    • 连边 $i o T$,流量为 $c_i$

    设最小割为 $x$,那么答案就是:

    $$sum_{i=1}^{n}sum_{j=1}^{n}b_{i,j} - x$$

    尽管有很多个点,但还是可以跑得很快的。(*^_^*)

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 typedef long long LL;
     8 #define N 250000 + 500 + 5
     9 #define M 2500000 + 5
    10 #define INF 0x7fffffff
    11 
    12 int n, S, T, cnt, tot = 1;
    13 int Head[N], q[N], Dfn[N];
    14 LL ans;
    15 
    16 struct Edge
    17 {
    18     int next, node, flow;
    19 }h[M];
    20 
    21 inline void addedge(int u, int v, int fl)
    22 {
    23     h[++ tot].next = Head[u], Head[u] = tot;
    24     h[tot].node = v, h[tot].flow = fl;
    25     h[++ tot].next = Head[v], Head[v] = tot;
    26     h[tot].node = u, h[tot].flow = 0;
    27 }
    28 
    29 inline bool BFS()
    30 {
    31     for (int i = S; i <= T; i ++)
    32         Dfn[i] = 0;
    33     int l = 1, r = 1;
    34     q[1] = S, Dfn[S] = 1;
    35     while (l <= r)
    36     {
    37         int z = q[l ++];
    38         for (int i = Head[z]; i; i = h[i].next)
    39         {
    40             int d = h[i].node, p = h[i].flow;
    41             if (!p || Dfn[d]) continue ;
    42             Dfn[d] = Dfn[z] + 1;
    43             q[++ r] = d;
    44             if (d == T) return 1;
    45         }
    46     }
    47     return 0;
    48 }
    49 
    50 inline int dinic(int z, int inflow)
    51 {
    52     if (z == T) return inflow;
    53     int ret = inflow, flow;
    54     for (int i = Head[z]; i; i = h[i].next)
    55     {
    56         int d = h[i].node, p = h[i].flow;
    57         if (Dfn[d] != Dfn[z] + 1 || !p) continue ;
    58         flow = dinic(d, min(p, ret));
    59         ret -= flow;
    60         h[i].flow -= flow, h[i ^ 1].flow += flow;
    61         if (!ret) return inflow;
    62     }
    63     if (ret == inflow) Dfn[z] = -1;
    64     return inflow - ret;
    65 }
    66 
    67 int main()
    68 {
    69     #ifndef ONLINE_JUDGE
    70         freopen("3996.in", "r", stdin);
    71         freopen("3996.out", "w", stdout);
    72     #endif
    73     
    74     scanf("%d", &n);
    75     S = 0, T = n + n * n + 1, cnt = n;
    76     for (int i = 1; i <= n; i ++)
    77         for (int j = 1, w; j <= n; j ++)
    78         {
    79             scanf("%d", &w);
    80             addedge(S, ++ cnt, w);
    81             addedge(cnt, i, INF);
    82             addedge(cnt, j, INF);
    83             ans += w;
    84         }
    85     for (int i = 1, w; i <= n; i ++)
    86     {
    87         scanf("%d", &w);
    88         addedge(i, T, w);
    89     }
    90     while (BFS())
    91         ans -= dinic(S, INF);
    92     printf("%lld
    ", ans);
    93     
    94     #ifndef ONLINE_JUDGE
    95         fclose(stdin);
    96         fclose(stdout);
    97     #endif
    98     return 0;
    99 }
    3996_Gromah
  • 相关阅读:
    Android短信管家视频播放器代码备份
    深入理解Android的startservice和bindservice
    Android拦截外拨电话
    android中的目录结构介绍
    2013年最后的3个月,你想到了什么呢?
    如何通过Html网页调用本地安卓app?
    Textview文字监控(输入到某个字符后,进行操作)
    ASP.NET MVC5 网站开发实践(二) Member区域
    ASP.NET MVC5 网站开发实践(二) Member区域
    ASP.NET MVC5 网站开发实践(一)
  • 原文地址:https://www.cnblogs.com/gromah/p/4451620.html
Copyright © 2020-2023  润新知