B. Ternary Sequence(贪心或最小费用最大流)

先 讲 贪 心 的 吧 先讲贪心的吧

设 a 0 表 示 a 数 组 0 元 素 , a 1 , a 2 , b 0 , b 1 , b 2 都 是 如 此 设a_0表示a数组0元素,a_1,a_2,b_0,b_1,b_2都是如此 a0a0,a1,a2,b0,b1,b2

只 有 当 a 2 和 b 1 匹 配 可 以 加 2 , 只 有 当 a 1 和 b 2 匹 配 可 以 减 2 只有当a_2和b_1匹配可以加2,只有当a_1和b_2匹配可以减2 a2b12,a1b22

其 他 匹 配 都 是 0 其他匹配都是0 0

思 路 是 , 先 拿 a 2 匹 配 b 1 思路是,先拿a_2匹配b_1 ,a2b1

原因很简单,只有这一种方法可以产生正贡献

至 于 你 担 心 也 许 拿 a 2 匹 配 b 2 会 更 优 . . . . 不 存 在 的 至于你担心也许拿a_2匹配b_2会更优....不存在的 a2b2....

拿 2 匹 配 1 让 答 案 + 2 是 最 好 的 , 因 为 只 影 响 了 b 的 一 个 元 素 拿2匹配1让答案+2是最好的,因为只影响了b的一个元素 21+2,b

这 个 元 素 在 后 续 的 影 响 最 多 是 − 2 , 那 也 不 会 让 让 答 案 变 坏 这个元素在后续的影响最多是-2,那也不会让让答案变坏 2,

然 后 拿 a 2 匹 配 b 2 ( 优 先 消 耗 b 大 的 数 字 ) 然后拿a_2匹配b_2(优先消耗b大的数字) a2b2(b)

然 后 拿 a 2 匹 配 b 0 ( 只 能 匹 配 b 0 了 ) 然后拿a_2匹配b_0(只能匹配b_0了) a2b0(b0)

然 后 拿 a 0 匹 配 b 2 ( 反 正 和 哪 个 b 匹 配 都 是 0 , 不 如 消 掉 最 大 的 ) 然后拿a_0匹配b_2(反正和哪个b匹配都是0,不如消掉最大的) a0b2(b0,)

然 后 拿 a 0 匹 配 b 1 然后拿a_0匹配b_1 a0b1

然 后 拿 a 0 匹 配 b 0 然后拿a_0匹配b_0 a0b0

然 后 只 剩 下 a 1 , 必 须 和 b 数 组 的 每 个 元 素 相 匹 配 了 然后只剩下a_1,必须和b数组的每个元素相匹配了 a1,b

我的代码写的比较粗犷,你可以改进一下自己写

#include 
using namespace std;
#define int long long
int t,a[5],b[5];
signed main()
{
	cin >> t;
	while( t-- )
	{
		for(int i=0;i<3;i++)	cin >> a[i];
		for(int j=0;j<3;j++)	cin >> b[j];
		//0��0�˷�
		int ans=0;
		int k=min( a[2],b[1] );//2��1��
		ans+=k*2;
		a[2]-=k,b[1]-=k;
		k=min( a[2],b[2] );
		a[2]-=k,b[2]-=k;
		b[0]-=a[2];
		k=min( a[1],b[1]);//��ģ��1 
		a[1]-=k,b[1]-=k;
		k=min( a[1],b[0] );
		a[1]-=k,b[0]-=k;
		ans-=a[1]*2;
		b[2]-=a[1];
		cout << ans << '\n';
	} 
}

还有叫做最小费用最大流的(不会的可以跳过哦)

因 为 最 近 在 刷 网 络 流 24 题 , 发 现 确 实 可 以 写 因为最近在刷网络流24题,发现确实可以写 24,

a 数 组 的 0 , 1 , 2 放 在 左 边 , b 数 组 的 0 , 1 , 2 放 在 右 边 a数组的0,1,2放在左边,b数组的0,1,2放在右边 a0,1,2,b0,1,2

这 构 成 了 一 个 二 分 图 , 每 个 对 应 的 匹 配 有 对 应 的 权 值 这构成了一个二分图,每个对应的匹配有对应的权值 ,

跑 最 大 匹 配 最 大 费 用 即 可 跑最大匹配最大费用即可

#include 
using namespace std;
const int maxn=50009;
const int inf=1e9;
int n,m,s,t,a[5],b[5];
int maxflow,maxcost;
int dis[maxn],head[maxn<<1],cnt=1,incf[maxn],pre[maxn],vis[maxn];
struct EDGE{
	int to,nxt,w,flow;//�ֱ���� 
}d[maxn<<1];
void add(int u,int v,int flow,int w)//flow�������,w�����
{
	d[++cnt].to=v,d[cnt].flow=flow,d[cnt].w=w,d[cnt].nxt=head[u],head[u]=cnt;
	d[++cnt].to=u,d[cnt].flow=0,d[cnt].w=-w,d[cnt].nxt=head[v],head[v]=cnt;	
} 
bool spfa()
{
	queue<int>q;
	for(int i=0;i<=t;i++)	dis[i]=-inf;
	memset(vis,0,sizeof(vis));
	q.push(s);
	dis[s]=0,vis[s]=1;
	incf[s] = inf;//��ʼ�������޴�
	while( !q.empty() )
	{
	//	cout << "��֪\n";
		int u=q.front(); q.pop();
		vis[u]=0;//����
		for(int i=head[u];i;i=d[i].nxt)
		{
			if( !d[i].flow )	continue;//��������	
			int v=d[i].to;
			if( dis[v]<dis[u]+d[i].w )
			{
				dis[v]=dis[u]+d[i].w;
				incf[v] = min(incf[u],d[i].flow);//���µ�ǰ����
				pre[v]=i;//��¼�������߹�����
				if( !vis[v] )	vis[v]=1,q.push(v); 
			}
		}	
	} 
	if( dis[t]==-inf )	return 0;
	return 1;
}
void dinic()
{
	while( spfa() )
	{
		int x=t;//����ȥ��·��
		maxflow+=incf[t];
		maxcost+=dis[t]*incf[t];
		int i;
		while(x != s)
		{
			i=pre[x];
			d[i].flow-=incf[t];//��ȥ����
			d[i^1].flow+=incf[t];//��������
			x = d[i^1].to;//��Ϊ�ǵ���ȥ,�������÷���ߵ���ȥ 
		} 
	}
}
int main()
{
	int T; cin >> T;
	while( T-- )
	{
		for(int i=0;i<=100;i++)	head[i]=0;
		cnt=1,maxcost=0;
		s=0,t=7;
		for(int i=1;i<=3;i++)	cin >> a[i];
		for(int i=1;i<=3;i++)	cin >> b[i];
		for(int i=1;i<=3;i++)
		{
			add(s,i,a[i],0);
			add(i+3,t,b[i],0);
		}
		for(int i=4;i<=6;i++)	add(1,i,a[1],0);
		add(2,4,a[2],0);
		add(2,5,a[2],0);
		add(2,6,a[2],-2);
		add(3,4,a[3],0);
		add(3,5,a[3],2);
		add(3,6,a[3],0);
		dinic();
		cout << maxcost << '\n';
	}
}

你可能感兴趣的:(div题解)