1 条题解

  • 0
    @ 2026-5-9 0:41:57

    之前居然不知道矩阵的转置是什么/qd,百度一下发现这就是把矩阵的横竖颠倒一下。

    然后进行一个柿子的推,发现 $D=\sum\limits_{i=1}^n a_i\ (\sum\limits_{j=1}^na_j\times b_{j,i}-c_i)$,由于 cic_i 这个东西的存在,且 aa0101 矩阵,所以考虑最小割。

    ai=1a_i=1 的点 ii 属于集合 SSai=0a_i=0 的点 ii 属于集合 TT,套路性地把每个点 ii 拆成横竖两个点 xix_iyiy_i,根据式子建图:

    • ai=0a_i=0 损失的贡献为 sumi=j=1nbj,isum_i=\sum\limits_{j=1}^n b_{j,i},可以表示为连边 (s,xi,sumi)(s,x_i,sum_i)
    • ai=1a_i=1aj=0a_j=0 损失的贡献为 bj,ib_{j,i},表示为连边 (xi,yj,bj,i) (ji)(x_i,y_j,b_{j,i})\ (j\ne i)i=ji=j 时不可能出现这种情况,即连边 (xi,yi,+)(x_i,y_i,+\infty)
    • ai=1a_i=1 要额外损失贡献 cic_i,即连边 (yi,t,ci)(y_i,t,c_i),当 iSi\in S 时强制切断这条边。

    跑 Dinic 即可,答案即 $ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^n b_{i,j}-$ 最小割。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,s,e) for(int i=(s);i<=(e);++i)
    #define Rep(i,s,e) for(int i=(e);i>=(s);--i)
    using namespace std;
    inline int read(){
        int x=0,f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    const int N=1010,M=1e6+5;
    int n,s,t,b[N>>1][N>>1],c[N],sum[N];
    int head[N],rad[N],cnt=1;
    struct qwq{
        int v,w,nxt;
    }e[M];
    inline void add(int u,int v,int w){
        e[++cnt]={v,w,head[u]},head[u]=cnt;
        e[++cnt]={u,0,head[v]},head[v]=cnt;
    }
    int dep[N];
    inline bool bfs(){
        queue<int> q;
        rep(i,1,t) dep[i]=0;
        dep[s]=1,q.push(s);
        while(!q.empty()){
            int x=q.front();q.pop();
            rad[x]=head[x];
            for(int i=head[x];i;i=e[i].nxt){
                int v=e[i].v,w=e[i].w;
                if(w&&!dep[v]) dep[v]=dep[x]+1,q.push(v);
            }
        }
        return dep[t]!=0;
    }
    int dfs(int x,int flow){
        if(x==t) return flow;
        int out=0;
        for(int &i=rad[x];i;i=e[i].nxt){
            int v=e[i].v,&w=e[i].w;
            if(w&&dep[v]==dep[x]+1){
                int res=dfs(v,min(flow,w));
                out+=res,flow-=res,w-=res,e[i^1].w+=res;
            }
            if(!flow) break;
        }
        if(flow) dep[x]=-1;
        return out;
    }
    signed main(){
        n=read(),s=n<<1|1,t=s+1;
        int ans=0,tmp;
        rep(i,1,n) rep(j,1,n) b[i][j]=read(),sum[j]+=b[i][j];
        rep(i,1,n) c[i]=read(),ans+=sum[i];
        rep(i,1,n){
            add(s,i,sum[i]),add(i+n,t,c[i]),add(i,i+n,1e9);
            rep(j,1,n) if(j!=i) add(i,j+n,b[j][i]);
        }
        while(bfs()) while(tmp=dfs(s,1e9)) ans-=tmp;
        // rep(i,1,t) cerr<<dep[i]<<' ';cerr<<endl;
        printf("%d\n",ans);
    }
    
    • 1

    信息

    ID
    5661
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者