先 讲 贪 心 的 吧 先讲贪心的吧 先讲贪心的吧
设 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都是如此 设a0表示a数组0元素,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 只有当a2和b1匹配可以加2,只有当a1和b2匹配可以减2
其 他 匹 配 都 是 0 其他匹配都是0 其他匹配都是0
思 路 是 , 先 拿 a 2 匹 配 b 1 思路是,先拿a_2匹配b_1 思路是,先拿a2匹配b1
原因很简单,只有这一种方法可以产生正贡献
至 于 你 担 心 也 许 拿 a 2 匹 配 b 2 会 更 优 . . . . 不 存 在 的 至于你担心也许拿a_2匹配b_2会更优....不存在的 至于你担心也许拿a2匹配b2会更优....不存在的
拿 2 匹 配 1 让 答 案 + 2 是 最 好 的 , 因 为 只 影 响 了 b 的 一 个 元 素 拿2匹配1让答案+2是最好的,因为只影响了b的一个元素 拿2匹配1让答案+2是最好的,因为只影响了b的一个元素
这 个 元 素 在 后 续 的 影 响 最 多 是 − 2 , 那 也 不 会 让 让 答 案 变 坏 这个元素在后续的影响最多是-2,那也不会让让答案变坏 这个元素在后续的影响最多是−2,那也不会让让答案变坏
然 后 拿 a 2 匹 配 b 2 ( 优 先 消 耗 b 大 的 数 字 ) 然后拿a_2匹配b_2(优先消耗b大的数字) 然后拿a2匹配b2(优先消耗b大的数字)
然 后 拿 a 2 匹 配 b 0 ( 只 能 匹 配 b 0 了 ) 然后拿a_2匹配b_0(只能匹配b_0了) 然后拿a2匹配b0(只能匹配b0了)
然 后 拿 a 0 匹 配 b 2 ( 反 正 和 哪 个 b 匹 配 都 是 0 , 不 如 消 掉 最 大 的 ) 然后拿a_0匹配b_2(反正和哪个b匹配都是0,不如消掉最大的) 然后拿a0匹配b2(反正和哪个b匹配都是0,不如消掉最大的)
然 后 拿 a 0 匹 配 b 1 然后拿a_0匹配b_1 然后拿a0匹配b1
然 后 拿 a 0 匹 配 b 0 然后拿a_0匹配b_0 然后拿a0匹配b0
然 后 只 剩 下 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放在右边 a数组的0,1,2放在左边,b数组的0,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';
}
}