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

首先,我们可以得到:

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

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

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

这是经典的最小割模型:

  • 连边 $S\to Dot(i,j)$,流量为 $b_{i,j}$。
  • 连边 $Dot(i,j)\to i$ 以及 $Dot(i,j)\to j$,流量为 $\infty$。
  • 连边 $i\to 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\n", ans);
93
94     #ifndef ONLINE_JUDGE
95         fclose(stdin);
96         fclose(stdout);
97     #endif
98     return 0;
99 }

3996_Gromah

时间: 2024-10-24 14:22:14

BZOJ 3996 [TJOI 2015] 线性代数 解题报告的相关文章

[BZOJ 3996] [TJOI 2015] 线性代数

3996: [TJOI2015]线性代数 Time Limit: 10 SecMemory Limit: 128 MB Description 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D Input 第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij. 接下来一行输入N个整数,代表矩阵C.矩阵B和矩阵C中每个数字都是不超过1000的非负整数. Output 输出最大的D Sampl

BZOJ 3997 [TJOI 2015 组合数学] 解题报告

这个题我脑洞了一个结论: 首先,我们定义满足以下条件的路径为“从右上到左下的路径”: 对于路径上任何不相同的两个点 $(x_1, y_1)$,$(x_2, y_2)$,都有: $x_1\neq x_2, y_1\neq y_2$ 若 $x_1 > x_2$,则有 $y_1 < y_2$:否则当 $x_1 < x_2$ 时, $y_1 > y_2$. 然后我们找到所有从右上到左下的路径,其中路径的权值和最大的那条路径的权值和就是答案了. 然后我们就可以用 Dp 解决问题了. 我们可以

BZOJ 3990 [SDOI 2015] 排序 解题报告

这个题哎呀...细节超级多... 首先,我猜了一个结论.如果有一种排序方案是可行的,假设这个方案是 $S$ . 那么我们把 $S$ 给任意重新排列之后,也必然可以构造出一组合法方案来. 于是我们就可以 $O(2^n)$ 枚举每个操作进不进行,再去判断,如果可行就 $ans$ += $|S|!$. 然而怎么判断呢? 我们按照操作种类从小到大操作. 假设我们现在在决策第 $i$ 种操作并且保证之前之后不需要进行种类编号 $< i$ 的操作. 那么我们只考虑那些位置在 $2^i+1$ 的位置的那些数.

[BZOJ 4001] [TJOI 2015] 概率论

4001: [TJOI2015]概率论 Time Limit: 10 SecMemory Limit: 128 MB Description Input 输入一个正整数N,代表有根树的结点数 Output 输出这棵树期望的叶子节点数.要求误差小于1e-9 Sample Input 1 Sample Output 1.000000000 HINT 1<=N<=10^9 Source [题解]拍个暴力,算算前5个,推了下公式,大概就是f(n)=n(n+1)/2/(2n-1) 然后就AC了=-= 1

BZOJ 4145 [AMPPZ2014] The Prices 解题报告

感觉也是一个小清新题.. 我们考虑设立状态 $Dp[i][s]$ 表示考虑了前 $i$ 个商店后,购买状态为 $s$ 的最小花费. 转移的话就枚举每个商店 $i$,首先令: $$Dp[i][s] = Dp[i - 1][s] + D[i]$$ 这个过程表示到达这个商店. 然后枚举每个状态 $s$,然后枚举每个不在 $s$ 里的物品 $j$,令: $$Dp[i][s + \{j\}] = min(Dp[i][s + \{j\}], Dp[i][s] + Cost[i][j])$$ 这个过程就相当于

BZOJ 3955 Surely You Congest 解题报告

首先,我们可以求出源为 $1$ 号点的最短路图以及各个点到 $1$ 号点的最短路. 然后我们考虑那些距离不同的点,是一定不会发生拥堵现象的. 然后我们就只需要考虑那些距离相同的点,就相当于做一个最大流嘛. 假设考虑与 $1$ 号节点距离为 $d$ 的点,那怎么连边,怎么设置源和汇呢? 源为 $1$ 号节点,新开一个 $n+1$ 号节点作为汇. 对于所有满足 $dist(1, x) + w(x,y) = dist(1, y)$ 的 $x,y$ 建一条 $x\rightarrow y$ 的边,容量为

[BZOJ 3997] [TJOI 2015] 组合数学

3997: [TJOI2015]组合数学 Time Limit: 20 SecMemory Limit: 128 MB Description 给出一个网格图,其中某些格子有财宝,每次从左上角出发,只能向下或右走.问至少走多少次才能将财宝捡完.此对此问题变形,假设每个格子中有好多财宝,而每一次经过一个格子至多只能捡走一块财宝,至少走多少次才能把财宝全部捡完. Input 第一行为正整数T,代表数据组数. 每组数据第一行为正整数N,M代表网格图有N行M列,接下来N行每行M个非负整数,表示此格子中财

[TJOI 2015] 线性代数

题目传送-Luogu3973 题意: 给定一个\(n×n\)的矩阵\(B\)和一个\(1×n\)的矩阵\(C\),求一个\(1×n\)的\(01\)矩阵\(A\).使得\(D=(A×B-C)×A^{\sf T}\)最大,其中\(A^{\sf T}\)为\(A\)的转置.输出\(D\). \(n \le 500,1 \le Allelement \le 1000\) 题解: emmm这是道网络流..二十多万条边跑网络流也是有信仰的了 脑补一下我们可以发现以下性质: 只有当\(a_i=1\)且\(a

解题报告 之 2015蓝桥杯 垒骰子

解题报告 之 2015蓝桥杯 垒骰子 赌圣 atm 晚年迷恋上了垒骰子,就是把骰子一个垒在还有一个上边.不能歪歪扭扭,要垒成方柱体. 经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥! 我们先来规范一下骰子:1 的对面是 4.2 的对面是 5,3 的对面是 6. 如果有 m 组相互排斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来. atm 想计算一下有多少种不同的可能的垒骰子方式. 两种垒骰子方式同样,当且仅当这两种方式中相应高度的骰子的相应数字的朝向都同