BZOJ 3996: [TJOI2015]线性代数

来源:互联网 发布:mac版音频剪辑 编辑:程序博客网 时间:2024/06/05 11:23

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

Sample Input

3

1 2 1

3 1 0

1 2 3

2 3 7

Sample Output

2

HINT

1<=N<=500

分析

倒腾下式子发现是经典最小割建模
然后,就没有然后了

代码

#include <bits/stdc++.h>#define N 300005#define ll long long#define INF 0x7fffffstruct NOTE{    int to,next,c;}e[N*20];int last[N];int cnt;void add(int x,int y,int c){    e[++cnt] = (NOTE) {y,last[x],c}; last[x] = cnt;    e[++cnt] = (NOTE) {x,last[y],0}; last[y] = cnt;}int dis[N];int cur[N];int ans;int s,t;bool bfs(){    for (int i = s; i <= t; i++)        dis[i] = 0;    dis[s] = 1;    std::queue<int> Q;    Q.push(s);    while (!Q.empty())    {        int u = Q.front();        Q.pop();        for (int i = last[u]; i; i = e[i].next)            if (e[i].c && !dis[e[i].to])            {                dis[e[i].to] = dis[u] + 1;                if (e[i].to == t)                    return 1;                Q.push(e[i].to);            }    }    return 0;}int dfs(int x,int maxf){    if (x == t || !maxf)        return maxf;    int ret = 0;    for (int &i = cur[x]; i; i = e[i].next)        if (e[i].c && dis[e[i].to] == dis[x] + 1)        {            int f = dfs(e[i].to,std::min(e[i].c,maxf - ret));            ret += f;            e[i].c -= f;            e[i^1].c += f;            if (ret == maxf)                break;        }    return ret;}void dinic(){    while (bfs())    {        for (int i = s; i <= t; i++)            cur[i] = last[i];        ans += dfs(s,INF);    }}int n;int main(){    scanf("%d",&n);    t = n + n * n + 1;    int id = n;    int tot = 0;    for (int i = 1; i <= n; i++)        for (int j = 1; j <= n; j++)        {            int x;            scanf("%d",&x);            id++;            tot += x;            add(i,id,INF);            add(j,id,INF);            add(id,t,x);        }    for (int i = 1; i <= n; i++)    {        int x;        scanf("%d",&x);        add(s,i,x);    }    dinic();    std::cout<<tot - ans<<std::endl;}
0 0
原创粉丝点击