其他分享
首页 > 其他分享> > P3973 [TJOI2015]线性代数

P3973 [TJOI2015]线性代数

作者:互联网

题意描述:

洛谷

给你一个 \(n\times n\) 的矩阵 \(B\) 和一个 \(1\times n\) 的矩阵 \(C\) , 让你求一个 \(1\times n\) 的 \(01\) 矩阵 \(A\), 使得: \(D = (A\times B - C)\times A^T\) 的值最大,输出这个最大值。

注: \(A^T\) 即 \(A\) 的转置,也就是将 \(A\) 的行和列交换后得到的矩阵。

数据范围: \(n\leq 500\) .

solution:

乍一看,可能一点思路都没有。

我们先把求和的式子展开:

\[(A\times B-C)\times A^T\\ = A\times B \times A^T - C\times A^T\\ = \displaystyle\sum_{i=1}^{n}\sum_{j=1}^{n} A_iA_jB_{ij} - \sum_{i=1}^{n} C_iA_i \]

然后你会发现,当 \(A_i = 1\) 的代价为 \(C_i\) 当 \(A_i\) 和 \(A_j\) 同为 \(1\) 的时候收益为 \(B_{ij}\) .

这就是一个最大权闭合子图的模型。

建图:

最后 \(b_{ij}\) 之和减去最小割就是答案。

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int inf = 1e7+10;
const int N = 1e6+10;
int n,cnt,sum,ans,s,t,tot = 1;
int head[N],dep[N],c[N],b[1010][1010],id[1010][1010];
struct node
{
	int to,net,w;
}e[N<<1];
inline int read()
{
    int s = 0, w = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    return s * w;
}
void add(int x,int y,int w)
{
	e[++tot].to = y;
	e[tot].w = w;
	e[tot].net = head[x];
	head[x] = tot;
}
bool bfs()
{
	queue<int> q;
	for(int i = 0; i <= t; i++) dep[i] = 0;
	q.push(s); dep[s] = 1;
	while(!q.empty())
	{
		int x = q.front(); q.pop();
		for(int i = head[x]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(e[i].w && !dep[to])
			{
				dep[to] = dep[x] + 1;
				q.push(to);
				if(to == t) return 1;
			}
		} 
	}
	return 0;
}
int dinic(int x,int flow)
{
	if(x == t || !flow) return flow;
	int rest = flow, val = 0;
	for(int i = head[x]; i && rest; i = e[i].net)
	{
		int to = e[i].to;
		if(!e[i].w || dep[to] != dep[x] + 1) continue;
		val = dinic(to,min(rest,e[i].w));	
		if(val == 0) dep[to] = 0;
		e[i].w -= val, e[i^1].w += val, rest -= val;
	} 
	return flow - rest;
} 
int main()
{
	n = read();
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			b[i][j] = read();
			id[i][j] = ++cnt;
		}
	}
	for(int i = 1; i <= n; i++) c[i] = read();
	s = 0, t = cnt + n + 1;
	for(int i = 1; i <= n; i++)//建图
	{
		for(int j = 1; j <= n; j++)
		{
			sum += b[i][j]; 
			add(s,id[i][j],b[i][j]), add(id[i][j],s,0);
			add(id[i][j],cnt+i,inf), add(cnt+i,id[i][j],0);
			add(id[i][j],cnt+j,inf), add(cnt+j,id[i][j],0);
		}
	}
	for(int i = 1; i <= n; i++) add(cnt+i,t,c[i]), add(t,cnt+i,0);
	int flow = 0;
	while(bfs())
	{
		while(flow = dinic(s,inf)) ans += flow;
	} 
	printf("%d\n",sum-ans);
	return 0;
}

标签:P3973,int,sum,times,ij,TJOI2015,线性代数,include,1010
来源: https://www.cnblogs.com/genshy/p/14409497.html