BZOJ3996 TJOI2015线性代数

先把矩阵式子化简

原式=i=1nj=1nA[i]B[i][j]A[j]i=1nA[i]C[i]

因此我们发现问题转化为选取一个点所获收益是B[i][j],代价是C[i][j]

这是一个最小割问题。

先把答案记做所有b的和。

将边按照s——>p[i][j](b[i][j])  p[i][j]——>i p[i][j]——>j i——>t(c[i])这样建图后我们删去的那个最小割意义就是花费最少的使得整个图不连通的量

如果删在左边就意味着这件物品我们不要了,如果删去右边的话就说明这件物品我们要付钱。

By:大奕哥

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1000005,inf=1e9;
 4 int head[N],cnt=-1,n,b[505][505],c[505];
 5 struct node{
 6     int to,nex,w;
 7 }e[4000005];
 8 void add(int x,int y,int w)
 9 {
10     e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;e[cnt].w=w;
11     e[++cnt].to=x;e[cnt].nex=head[y];head[y]=cnt;e[cnt].w=0;
12 }
13 int d[N],v[N],s,t;
14 queue<int>q;
15 bool bfs()
16 {
17     memset(v,0,sizeof(v));
18     memset(d,-1,sizeof(d));
19     d[s]=0;q.push(s);
20     while(!q.empty())
21     {
22         int x=q.front();q.pop();v[x]=1;
23         for(int i=head[x];i!=-1;i=e[i].nex)
24         {
25             int y=e[i].to;
26             if(d[y]!=-1||!e[i].w)continue;
27             d[y]=d[x]+1;
28             if(!v[y]){
29                 q.push(y);v[y]=1;
30             }
31         }
32     }
33     return d[t]!=-1;
34 }
35 int dfs(int x,int w,int yy)
36 {
37     if(!w||x==yy)return w;
38     int s=0;
39     for(int i=head[x];i!=-1;i=e[i].nex)
40     {
41         int y=e[i].to;
42         if(d[y]!=d[x]+1||!e[i].w)continue;
43         int flow=dfs(y,min(e[i].w,w-s),yy);
44         if(!flow)d[y]=-1;
45         e[i].w-=flow;e[i^1].w+=flow;s+=flow;
46         if(s==w)return s;
47     }
48     return s;
49 }
50 int main()
51 {
52     scanf("%d",&n);int sum=0,num=0;
53     memset(head,-1,sizeof(head));
54     for(int i=1;i<=n;++i)
55     for(int j=1;j<=n;++j)
56     {
57         scanf("%d",&b[i][j]);
58     }
59     t=n*n+n+10;
60     for(int i=1;i<=n;++i)
61     scanf("%d",&c[i]),add(i+n*n,t,c[i]);
62     for(int i=1;i<=n;++i)
63     for(int j=1;j<=n;++j)
64     {
65         sum+=b[i][j];
66         add(s,++num,b[i][j]);
67         add(num,i+n*n,inf);
68         add(num,j+n*n,inf);
69     }
70     while(bfs()){
71         sum-=dfs(s,1e9,t);
72     }
73     printf("%d\n",sum);
74     return 0;
75 }

 

转载于:https://www.cnblogs.com/nbwzyzngyl/p/8442918.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值