zoukankan      html  css  js  c++  java
  • BZOJ3996[TJOI2015]线性代数——最小割

    题目描述

    给出一个N*N的矩阵B和一个1*N的矩阵C。求出一个1*N的01矩阵A.使得

    D=(A*B-C)*A^T最大。其中A^T为A的转置。输出D

    输入

    第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij.
    接下来一行输入N个整数,代表矩阵C。矩阵B和矩阵C中每个数字都是不超过1000的非负整数。

    输出

    输出最大的D

    样例输入

    3
    1 2 1
    3 1 0
    1 2 3
    2 3 7

    样例输出

    2

    提示

     1<=N<=500

    如果没有C矩阵,答案就是B矩阵中每个数的和假设为ans,那么有了C矩阵,我们就是想使ans减小的尽量少。

    对于C中每个元素,要么就是ans直接减掉这个元素的值,也就是A中对应位置选1;要么就是不要B中的一些元素,也就是A中一些的位置选0来防止ans减掉这个C中元素的值。

    那么这个问题就可转化成最小割,将S连向B中每个点,流量为对应B中的点权值;将B中每个点连向这个点对应的行和列代表的点,流量为INF;最后再将列代表的点连向汇点,流量为C中对应点的权值。

    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<bitset>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 0x3f3f3f3f
    using namespace std;
    int next[5000001];
    int to[5000001];
    int val[5000001];
    int head[1000001];
    int tot=1;
    int q[1000001];
    int bak[1000001];
    int n,x;
    int S,T;
    int ans;
    int sum;
    int d[1000001];
    void add(int x,int y,int v)
    {
        tot++;
        next[tot]=bak[x];
        bak[x]=tot;
        to[tot]=y;
        val[tot]=v;
        tot++;
        next[tot]=bak[y];
        bak[y]=tot;
        to[tot]=x;
        val[tot]=0;
    } 
    bool bfs(int S,int T)
    {
        int r=0;
        int l=0;
        memset(d,-1,sizeof(d));
        q[r++]=T;
        d[T]=2;
        while(l<r)
        {
            int now=q[l];
            for(int i=bak[now];i;i=next[i])
            {
                if(d[to[i]]==-1&&val[i^1]!=0)
                {
                    d[to[i]]=d[now]+1;
                    q[r++]=to[i];
                }
            }
            l++;
        }
        if(d[S]==-1)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    int dfs(int x,int flow)
    {
        if(x==T)
        {
            return flow;
        }
        int now_flow;
        int used=0;
        for(int &i=head[x];i;i=next[i])
        {
            if(d[to[i]]==d[x]-1&&val[i]!=0)
            {
                now_flow=dfs(to[i],min(flow-used,val[i]));
                val[i]-=now_flow;
                val[i^1]+=now_flow;
                used+=now_flow;
                if(now_flow==flow)
                {
                    return flow;
                }
            }
        }
        if(used==0)
        {
            d[x]=-1;
        }
        return used;
    }
    void dinic()
    {
        while(bfs(S,T)==true)
        {
            memcpy(head,bak,sizeof(bak));
            ans+=dfs(S,INF);
        }
    }
    int main()
    {
        scanf("%d",&n);
        S=n*n+n+1;
        T=n*n+n+2;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&x);
                sum+=x;
                add(S,(i-1)*n+j,x);
                add((i-1)*n+j,n*n+i,INF);
                add((i-1)*n+j,n*n+j,INF);
            }
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            add(n*n+i,T,x);
        }
        dinic();
        printf("%d",sum-ans);
    }
  • 相关阅读:
    SVN同步版本库与网站目录2
    SVN同步版本库与网站目录
    vsftpd配置手册(实用)
    Yii中的CComponent应用实例
    js中文乱码
    yii CComponent组件 实例说明1
    try...cath...finally中的return什么时候执行
    Jmeter之Constant Timer与constant throughput timer的区别
    cookie、session、sessionid ,jsessionid 的区别
    性能测试基本概念
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9740761.html
Copyright © 2011-2022 走看看