不错的题,就是听说数据有点水,似乎A矩阵全1就能过。。。。。。。。。
Pro:
https://www.luogu.com.cn/problem/P3973
Sol:
推一下题目说的那个式子。
发现要最大化这个一个东西
[sum_{i=1}^nsum_{j=1}^n a_i*a_j*b_{i,j}-sum_{i=1}^n a_i*c_i
]
这个东西很容易联想到一个经典的模型----------最大权闭合子图
有一些东西收益为正,有一些东西收益为负,有一些限制,限制的形式是选了A就必须选B
那么就按照这个套路建个图,n✖n个正收益物品,n个负收益物品,跑一下网络流即可。
#include<bits/stdc++.h>
#define N 1100000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
using namespace std;
inline int read()
{
char ch=0;
int x=0,flag=1;
while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*flag;
}
struct edge{int to,nxt,w;}e[N*2];
int num,head[N];
inline void add(int x,int y,int z)
{
e[++num]={y,head[x],z};head[x]=num;
e[++num]={x,head[y],0};head[y]=num;
}
queue<int>q;
int s,t,size,dep[N],cur[N];
bool bfs()
{
for(int i=0;i<=size;i++)dep[i]=0,cur[i]=head[i];
q.push(s);dep[s]=1;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=head[x];i!=-1;i=e[i].nxt)
{
int to=e[i].to;
if(!dep[to]&&e[i].w)q.push(to),dep[to]=dep[x]+1;
}
}
return dep[t];
}
int dfs(int x,int flow)
{
if(x==t)return flow;
for(int i=cur[x];i!=-1;i=e[i].nxt)
{
cur[x]=i;
int to=e[i].to;
if(dep[to]==dep[x]+1&&e[i].w)
{
int w=dfs(to,min(flow,e[i].w));
if(w)
{
e[i].w-=w;
e[i^1].w+=w;
return w;
}
}
}
return 0;
}
int solve()
{
int ans=0;
while(bfs())
{
int w;
do{w=dfs(s,inf),ans+=w;}while(w);
}
return ans;
}
int main()
{
int n=read(),ans=0;
s=n*n+n+1;t=n*n+n+2;
num=-1;memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
{
int x=read();ans+=x;
add(s,++size,x);
add(size,n*n+i,inf);
add(size,n*n+j,inf);
}
for(int i=1;i<=n;i++)add(++size,t,read());size+=2;
printf("%d",ans-solve());
return 0;
}