problem

给定 nnn 个数 {ai}\{a_i\}{ai​},其中 kkk 个 aia_iai​ 是奇数,再给一个 n×nn\times nn×n 的矩阵 {ci,j}\{c_{i,j}\}{ci,j​},无论是 aaa 还是 ccc,都保证是非负整数。

现在可以做一类操作:将 ai−1,aj−1a_i-1,a_j-1ai​−1,aj​−1,花费 ci,jc_{i,j}ci,j​ 代价,i,ji,ji,j 可以相同。

要求把所有的 {ai}\{a_i\}{ai​} 全都变为 000。

求最小花费,无解输出 −1-1−1。

n≤50,k≤8n\le 50,k\le 8n≤50,k≤8,保证 ci,j=cj,ic_{i,j}=c_{j,i}ci,j​=cj,i​。

solution

显然,每次操作都会使得 (∑ai)−2(\sum a_i)-2(∑ai​)−2。所以如果 ∑ai\sum a_i∑ai​ 是奇数,即 aia_iai​ 为奇数的 iii 有奇数个,则无解。

接下来再来解决有解的问题。

先考虑 k=0k=0k=0 的弱化版。

那就存在欧拉回路,要求每个点的入度和出度相同,经典网络流模型转化。

将每个点拆成两个点,各放左右部,与源/汇点的连边流量设置为 ai2\frac{a_i}22ai​​。

花费针对“关系”而言,左右部点之间连边流量无穷带花费。

直接跑最小费用流即可。

转化思考:

如果操作 i,ji,ji,j,就在图上连一条 (i,j)(i,j)(i,j) 的边。那么最后这张图可能有重边和若干个环。

发现这是一张欧拉图,存在欧拉回路。我们能找到一种定向方式使得每个点的入度和出度相同。

推出存在一种最优方案使得每个点的入度和出度相同。

将每个点拆成入度点和出度点,转化成匹配问题。

现在有几个特殊点是奇数,欧拉回路不存在,变成存在欧拉路径。

我们先通过若干次操作将这些奇数全都消成偶数,就又转化成了欧拉回路,就可以套用上面的方法。

转化思考:

我们通过对图上进行加边,使得这张图最后仍是存在欧拉回路的图。

由此推出存在一种最优方案使得奇数点的入度和出度只相差 111。

由于 kkk 非常小,我们大可直接状压枚举哪一半的奇数点是入度多 111,剩下的就肯定是出度多 111。

还是转化成了入度和出度二分图的匹配问题,仍然跑个最小费用流。

最后求个 min⁡\minmin 就完了。

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 200
#define inf 0x7f7f7f7f
struct node { int to, nxt, flow, cost; }E[maxn * maxn];
int head[maxn], dis[maxn], lst[maxn], a[maxn], b[maxn], id[maxn];
int c[maxn][maxn];
bool vis[maxn];
int n, cnt, m, s, t;
queue < int > q;void addedge( int u, int v, int flow, int cost ) {E[++ cnt] = { v, head[u], flow, cost }, head[u] = cnt;E[++ cnt] = { u, head[v], 0, - cost }, head[v] = cnt;
}bool SPFA() {memset( lst, -1, sizeof( lst ) );memset( dis, 0x7f, sizeof( dis ) );dis[s] = 0, q.push( s );while( ! q.empty() ) {int u = q.front(); q.pop(); vis[u] = 0;for( int i = head[u];~ i;i = E[i].nxt ) {int v = E[i].to;if( dis[v] > dis[u] + E[i].cost and E[i].flow ) {dis[v] = dis[u] + E[i].cost; lst[v] = i;if( ! vis[v] ) vis[v] = 1, q.push( v );}}}return ~ lst[t];
}int solve() {memset( head, -1, sizeof( head ) ), cnt = -1;for( int i = 1;i <= n;i ++ )for( int j = 1;j <= n;j ++ )addedge( i, j + n, inf, c[i][j] );for( int i = 1;i <= n;i ++ ) {addedge( s, i, a[i] + b[i] >> 1, 0 );addedge( i + n, t, a[i] - b[i] >> 1, 0 );}int ans = 0;while( SPFA() ) {int flow = inf;for( int i = lst[t];~ i;i = lst[E[i ^ 1].to] )flow = min( flow, E[i].flow );ans += flow * dis[t];for( int i = lst[t];~ i;i = lst[E[i ^ 1].to] ) {E[i ^ 1].flow += flow;E[i].flow -= flow;}}return ans;
}int main() {scanf( "%d", &n ); s = 0, t = n << 1 | 1;for( int i = 1;i <= n;i ++ ) {scanf( "%d", &a[i] );if( a[i] & 1 ) id[m ++] = i;}for( int i = 1;i <= n;i ++ )for( int j = 1;j <= n;j ++ )scanf( "%d", &c[i][j] );if( m & 1 ) return ! puts("-1");int ans = inf;for( int i = 0;i < (1 << m);i ++ ) {for( int j = 0;j < m;j ++ )if( i >> j & 1 ) b[id[j]] = 1;else b[id[j]] = -1;if( __builtin_popcount( i ) ^ (m >> 1) ) continue;ans = min( ans, solve() );}printf( "%d\n", ans );return 0;
}

一般图带权多重匹配(欧拉图+最小费用流)相关推荐

  1. 二分图带权匹配、最佳匹配与KM算法

    ---------------------以上转自ByVoid神牛博客,并有所省略.   [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值 ...

  2. 【网络流24题】解题报告:E 、圆桌问题(最大流求二分图多重匹配)

    E .圆桌问题(最大流求二分图多重匹配)[省选/NOI- ] 可以直观的想到,二分图的左边是单位,右边是桌子 由于题目的限制 每个单位只能在一个桌子坐一个人 所以我们就把每个单位向各个桌子连一道流量为 ...

  3. POJ - 2289 Jamie's Contact Groups(二分图多重匹配)

    题目链接:点击查看 题目大意:给出n个联系人,以及m个分组,现在需要将n个联系人分到m个分组中,需要满足让人数最多的组的人数最少,输出这个值 题目分析:因为是让最大值最小,所以肯定是要用二分解决,因为 ...

  4. POJ - 3189 Steady Cow Assignment(二分图多重匹配)

    题目链接:点击查看 题目大意:给出n只奶牛以及m个牛棚,接下来给出一个n*m的矩阵,给出每一只奶牛对于每个牛棚的喜爱度,按照降序给出,从rank1到rankm,现在问如何分配牛棚能让所有奶牛中最高的r ...

  5. HDU - 3605 Escape(二分图多重匹配-网络流最大流+思维建边+状态压缩)

    题目链接:点击查看 题目大意:到世界末日了,现在人们要逃离去其他的星球,现在给出n个人以及m个星球,再给出每个人可以前往的星球,最后给出每个星球的容量,题目问最多能让多少个人逃离 题目分析:这个题读完 ...

  6. CH - 6803 导弹防御塔(二分图最大匹配-多重匹配(拆点法))

    题目链接:点击查看 题目大意:给出n个炮塔,再给出m个敌人,每个炮塔都可以持续发射导弹,不过发射导弹的时间是t1秒,炮塔冷却的时间是t2分钟,炮弹飞行的速度是v,炮塔和敌人之间的距离按照欧几里得距离计 ...

  7. 图论:二分图多重匹配

    使用最大流和费用流解决二分图的多重匹配 之前编辑的忘存了好气啊.. 本来打算学完二分图的乱七八糟的匹配之后再去接触网络流的,提前撞到了 之前我们说的二分图最大匹配和二分图最大权匹配有一个特点,那就是没 ...

  8. Uvalive3353 Optimal Bus Route Design 带权二分图匹配

    题目描述:给出一个有向带权图,现在要求在图中找出若干个环,使得每个点恰好在一个环里,且所有环的距离之和最小,如果不能使每个点恰好在一个环里,输出"N". 思路: 将每个点u拆成u和 ...

  9. 带权二分图匹配(最小费用最大流) 8.2牛客暑期多校训练营五 E

    E.room | 时间限制:1 秒 | 内存限制:256M Nowcoder University has 4n students and n dormitories ( Four students ...

最新文章

  1. SpringMVC请求流程
  2. ASP.NET Core SameSite 设置引起 Cookie 在 QQ 浏览器中不起作用
  3. VC++动态链接库DLL编程深入浅出
  4. 程序设计与算法----递归汉诺塔问题
  5. Android ListView 指定显示最后一行
  6. Django 2.0 报错解决方案----持续更新中
  7. nodejs fs模块
  8. 八大排序算法—源代码(c语言)
  9. VC密码正确无法登陆。证书过期。处理。
  10. android设置默认程序图标,android – 更改默认系统应用程序图标
  11. aws篇1 aws-cli的使用
  12. 阿里云Centos6数据盘扩容的问题处理
  13. 计算机知识动画片,这些好看的动画片里竟然藏着许多知识点!(内附2019年观影日历)...
  14. zoj 3551 Bloodsucker (概率dp)
  15. Cesium学习资源
  16. 从头开始绘制一个圆锥体
  17. 计算机网络——各层次网络互联设备
  18. C# QRCode生成二维码,支持中文,有utf
  19. 桌面上 计算机 图标打不开,突然间电脑桌面上的所有图标都打不开了,怎么回事,求大神讲解...
  20. Spyder 打开失败问题解决

热门文章

  1. 有些人还活着,被你一按就死了。。 | 今日最佳
  2. 编程语言的“别样”编年史
  3. 天赋差的程序员,难道就只能半途而废吗?
  4. c语言md5函数 linux,Linux下C语言计算文件的md5值(长度32)
  5. java 方法执行结束局部变量释放_Java方法执行的内存模型
  6. java反射 获取局部变量_Java反射:如何获取变量的名称?
  7. java中如何运行小程序_一起学java(一)——运行第一个小程序
  8. c语言怎样表示运行时间,C语言运行时间
  9. qtabwidget设置tab高度_VC|富文本编辑框CRichEditCtrl的字体与段落设置
  10. python求函数极值_python 遗传算法求函数极值的实现代码