OTL@assassain

反转源汇的模型: 给定一个二分图,同时选择集合中的两个点会有一个代价,选择每一个点有一个收益,问最大收益是多少

(即两个点在不同的集合中是有冲突关系的)

解法: 用最小割模型解决,通过反转源汇来表示冲突关系,用源S汇T表示选或不选,左边的黑点向S连黑点选择的收益(如果这条边割掉了就代表没有选择这个黑点,要减掉这个代价),向T连黑点不选择的收益(可以没有)。右边的白点向S连白点不选择的收益,向T连白点选择的收益(此时把S,T和上述反转了一下)。那么原图中两个点共同选择的代价就是在网络流图中直接连原来的权值即可

其实模型和另外一个模型很有对比意义,即最大权闭合子图

模型是给定一个二分图,选择其中一个点会有另一个点必须被选择(这时可以用inf的边来表示冲突关系),选择的收益有正有负(也可以看做有加有减),问最大收益。

那么此时两个点在相同的集合中是没有矛盾的,在不同的集合中是有代价的,此时不需要反转源汇,直接建图跑最小割就可以了

最大利益 = 所有点正权值之和 - 最小割

/*--------------------------------华丽丽的分割线--------------------------------*/

[国家集训队2011]圈地计划 网格图黑白染色,注意连双向边

#define MAXN 110
#include <bits/stdc++.h> using namespace std;
const int inf = 0x7fffffff / 2;
const int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1}; int n, m, S, T, a[MAXN][MAXN], b[MAXN][MAXN], c[MAXN][MAXN];
int h[MAXN*MAXN], cnt = 1;
struct Edge { int to, nxt, w; } edge[2000010];
void addedge(int u, int v, int w) {
edge[++ cnt] = (Edge){v, h[u], w}; h[u] = cnt;
edge[++ cnt] = (Edge){u, h[v], 0}; h[v] = cnt;
} int que[MAXN*MAXN], d[MAXN*MAXN];
bool BFS() {
int head = 0, tail = 0;
for(int i = S ; i <= T ; ++ i) d[i] = -1;
que[tail ++] = S, d[S] = 0;
while(head != tail) {
int u = que[head ++];
for(int i = h[u] ; i ; i = edge[i].nxt) {
if(edge[i].w == 0) continue;
int v = edge[i].to;
if(d[v] == -1) d[v] = d[u] + 1, que[tail ++] = v;
}
} return d[T] != -1;
} int DFS(int x, int a) {
if(x == T || a == 0) return a;
int used = 0, f;
for(int i = h[x] ; i ; i = edge[i].nxt) {
int v = edge[i].to;
if(d[v] == d[x] + 1) {
f = DFS(v, min(a-used, edge[i].w));
edge[i].w -= f;
edge[i^1].w += f;
used += f;
if(used == a) return used;
}
}
if(!used)d[x] = -1;
return used;
} int Dinic() {
int ret = 0;
while(BFS())
ret += DFS(S, inf);
return ret;
} int main() {
freopen("nt2011_land.in", "r", stdin);
freopen("nt2011_land.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1 ; i <= n ; ++ i)
for(int j = 1 ; j <= m ; ++ j)
scanf("%d", &a[i][j]);
for(int i = 1 ; i <= n ; ++ i)
for(int j = 1 ; j <= m ; ++ j)
scanf("%d", &b[i][j]);
for(int i = 1 ; i <= n ; ++ i)
for(int j = 1 ; j <= m ; ++ j)
scanf("%d", &c[i][j]);
static int id[MAXN][MAXN], idfclock = 0;
for(int i = 1 ; i <= n ; ++ i)
for(int j = 1 ; j <= m ; ++ j)
id[i][j] = ++ idfclock;
S = 0, T = ++ idfclock;
for(int i = 1 ; i <= n ; ++ i)
for(int j = 1 ; j <= m ; ++ j) {
if(i + j & 1) {
addedge(S, id[i][j], a[i][j]);
addedge(id[i][j], T, b[i][j]);
}
else {
addedge(S, id[i][j], b[i][j]);
addedge(id[i][j], T, a[i][j]);
}
for(int k = 0 ; k < 4 ; ++ k) {
int x = i + dx[k], y = j + dy[k];
if(id[x][y])addedge(id[i][j], id[x][y], c[i][j] + c[x][y]);
}
}
int ans = 0;
for(int i = 1 ; i <= n ; ++ i)
for(int j = 1 ; j <= m ; ++ j) {
int cn = 0;
for(int k = 0 ; k < 4 ; ++ k) {
int x = i + dx[k], y = j + dy[k];
if(id[x][y]) cn ++;
}
ans += a[i][j] + b[i][j] + c[i][j] * cn;
} printf("%d\n", ans - Dinic());
return 0;
}

[国家集训队2011]男生女生

求一个最大的二分图的子图,使得左边的每一个点向右边的每一个点都有边相连(第一问)

转化成最小割模型后,表示的冲突关系是左边选择一个点,右边和它没有边相连的点就不能选择。

选择一个点的收益为1,不选择的收益为0

那么这道题的建图就是从S->左边的点,右边的点->T连边,中间因为永远不能割断所以边权为inf

还有一些特殊的地方需要处理,但是和反转源汇建图没有太大关系,因此不再赘述

#define MAXN 105
#include <bits/stdc++.h> using namespace std;
const int inf = 0x7fffffff, md = 19921228; int n, m, k;
bool a[MAXN][MAXN]; int h[MAXN], cnt = 1, S, T;
struct Edge { int to, nxt, w; } edge[1000010];
void addedge(int u, int v, int w) {
edge[++ cnt] = (Edge){v, h[u], w}; h[u] = cnt;
edge[++ cnt] = (Edge){u, h[v], 0}; h[v] = cnt;
} int d[MAXN], que[MAXN]; bool BFS() {
int head = 0, tail = 0;
memset(d, -1, sizeof d);
que[tail ++] = S, d[S] = 0;
while(head != tail) {
int u = que[head ++];
for(int i = h[u] ; i ; i = edge[i].nxt) {
if(!edge[i].w) continue;
int v = edge[i].to;
if(d[v] == -1) que[tail ++] = v, d[v] = d[u] + 1;
}
} return d[T] != -1;
} int DFS(int x, int a) {
if(x == T || a == 0) return a;
int used = 0, f;
for(int i = h[x] ; i ; i = edge[i].nxt) {
int v = edge[i].to;
if(d[v] == d[x] + 1) {
f = DFS(v, min(a-used, edge[i].w));
edge[i].w -= f;
edge[i^1].w += f;
used += f;
if(used == a) return used;
}
}
if(!used)d[x] = -1;
return used;
} int Dinic() {
int ret = 0;
while(BFS())
ret += DFS(S, inf);
return ret;
} int main() {
freopen("boygirl.in", "r", stdin);
freopen("boygirl.out", "w", stdout);
scanf("%d%d%d", &n, &k, &m);
int u, v;
for(int i = 1 ; i <= m ; ++ i) {
scanf("%d%d", &u, &v);
a[u][v] = true;
} T = n+n+1;
for(int i = 1 ; i <= n ; ++ i) {
addedge(S, i, 100), addedge(i+n, T, 99);
for(int j = 1 ; j <= n ; ++ j)
if(!a[i][j])addedge(i, j+n, inf);
} int fw = Dinic();
int a = fw - fw/99*99, b = fw/99 - a;
a = n-a, b = n-b; static int C[2510][2510];
static long long f[MAXN][MAXN];
memset(C, 0, sizeof C);
memset(f, 0, sizeof f); for(int i = 0 ; i <= a*b ; ++ i) {
C[i][0] = 1;
for(int j = 1 ; j <= i ; ++ j)
C[i][j] = (C[i-1][j] + C[i-1][j-1]) % md;
} for(int i = 1 ; i <= a ; ++ i) {
for(int j = 1 ; j <= b ; ++ j) {
f[i][j] = C[i*j][k];
for(int k = 1 ; k <= i ; ++ k)
for(int l = 1 ; l <= j ; ++ l)
if(i != k || l != j)
f[i][j] = (f[i][j] - f[k][l]*C[i][k]%md*C[j][l]%md + md) % md;
}
} printf("%d %d\n%lld\n", a, b, f[a][b]);
return 0;
}

  

[二分图&最小割]的更多相关文章

  1. BZOJ 3275: Number (二分图最小割)

    题意 有nnn个数,其中同时满足下面两个条件的数对不能同时选,求选出一些数让和最大. 若两个数aaa,bbb同时满足以下条件,则aaa,bbb不能同时被选 存在正整数ccc,使a∗a+b∗b=c∗ca ...

  2. bzoj 3158 千钧一发(最小割)

    3158: 千钧一发 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 767  Solved: 290[Submit][Status][Discuss] ...

  3. [TJOI2013]攻击装置(网络流,最小割)

    前言 网络流被hbx吊起来打 Solution 考虑一下这个走法是不是和象棋中马的走法一模一样(废话) 那么显然我每一次移动是走三次,如果将棋盘二分图染色一下,不就是每一次只能走到另一个颜色的吗? 然 ...

  4. 1934. [SHOI2007]善意的投票【最小割】

    Description 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可 ...

  5. 二分图&网络流&最小割等问题的总结

    二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 技巧: 1.拆点为边,即一个点有限制,可将其转化为边 BZOJ1066, ...

  6. POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)

    题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...

  7. POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割

    思路来源:http://blog.csdn.net/lenleaves/article/details/7873441 求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边, 只要用最终的剩余网络 ...

  8. 【最小割/二分图最大独立集】【网络流24题】【P2774】 方格取数问题

    Description 给定一个 \(n~\times~m\) 的矩阵,每个位置有一个正整数,选择一些互不相邻的数,最大化权值和 Limitation \(1~\leq~n,~m~\leq~100\) ...

  9. 【LA3415 训练指南】保守的老师 【二分图最大独立集,最小割】

    题意 Frank是一个思想有些保守的高中老师.有一次,他需要带一些学生出去旅行,但又怕其中一些学生在旅行中萌生爱意.为了降低这种事情发生的概率,他决定确保带出去的任意两个学生至少要满足下面四条中的一条 ...

随机推荐

  1. MySQL性能优化的最佳经验

    今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数据 ...

  2. 【云计算】Docker云平台—Docker基础

    Docker云平台系列共三讲,此为第一讲:Docker基础 参考资料: Docker官方文档:https://docs.docker.com/ Docker从入门到实践:https://yeasy.g ...

  3. BASH相关

    颜色 http://www.cnblogs.com/lr-ting/archive/2013/02/28/2936792.html http://segmentfault.com/q/10100000 ...

  4. linux shell脚本守护进程监控svn服务

    最近搭建的svn服务不知道什么原因服务总是被关闭(如果你不知道怎么搭建svn可以参考linux下搭建svn版本控制软件),因此用shell脚本实现一个守护进程.用于监控svn服务是否启动,如果服务不在 ...

  5. zpf 视图

    2014年8月19日 18:12:16 smarty使用了2年, 使用PHP本身做模版引擎也有4个多月了, 最终还是在我的这个框架中抛弃了smarty,转用原生的PHP代码做模版引擎,并简单写了一个视 ...

  6. ECSHOP修改后台地址

    为了保证ECSHOP商城安全,需要修改许多默认的程序路径,今天讲下后台路径修改. ECSHOP修改后台路径根据版本不同,修改的地方也不一样.我现在用的是2.7.3,上网查了资料,很少,所以自己先写下来 ...

  7. 中石油-高精度阶乘-java

    问题 F: [高精度]高精度阶乘 时间限制: 1 Sec  内存限制: 64 MB提交: 49  解决: 13[提交][状态][讨论版] 题目描述 <魔法宝典>对于修罗王是如此重要,是因为 ...

  8. springMVC获取file,几种转换

    //从前台通过name值获取file MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)reque ...

  9. Human Gene Functions(poj 1080)

    题目大意是:给定两组DNA序列,要你求出它们的最大相似度 每个字母与其他字母或自身和空格对应都有一个打分,求在这两个字符串中插入空格,让这两个字符串的匹配分数最大 /* 思路是很好想的,设f[i][j ...

  10. Linux设置IP

    进入 vi /etc/sysconfig/network-scripts/ifcfg-eth0  root # ifconfig eth0 192.168.22.232 root # route ad ...