二分图带权最大独立集 网络流解决 hdu 1569
方格取数(2)
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3663 Accepted Submission(s): 1148
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
75 15 21
75 15 28
34 70 5
最大点权独立集=总权值-最小点权覆盖集
最小割=最大流
最小点权覆盖集=最小割
根据奇偶建立二分图,
if(i+j)%2==0 源点和该点连接,权值为该点的点权,
if(i+j)%2==1 该点和汇点连接,权值为该点的点权,
之后若i+j为偶数的点和i+j为奇数的点之间相邻,那么就连一条从为偶数的点到为奇数的点的边,权值为无穷大
之后 所有权值-最大流 即可
#include <stdio.h>
#include <string.h>
#define VM 2555
#define EM 2055000
#define inf 0x3f3f3f3f
struct Edge
{
int frm,to,cap,next;
}edge[EM]; int head[VM],dep[VM],ep; //dep为点的层次
void addedge (int cu,int cv,int cw) //第一条边下标必须为偶数
{
edge[ep].frm = cu;
edge[ep].to = cv;
edge[ep].cap = cw;
edge[ep].next = head[cu];
head[cu] = ep;
ep ++;
edge[ep].frm = cv;
edge[ep].to = cu;
edge[ep].cap = 0;
edge[ep].next = head[cv];
head[cv] = ep;
ep ++;
} int BFS (int src,int des) //求出层次图
{
int que[VM],i,front = 0,rear = 0;
memset (dep,-1,sizeof(dep));
que[rear++] = src;
dep[src] = 0;
while (front != rear)
{
int u = que[front++];
front = front%VM;
for (i = head[u];i != -1;i = edge[i].next)
{
int v = edge[i].to;
if (edge[i].cap > 0&&dep[v] == -1) //容量大于0&&未在dep中
{
dep[v] = dep[u] + 1; //建立层次图
que[rear ++] = v;
rear = rear % VM;
if (v == des) //找到汇点 返回
return 1;
}
}
}
return 0;
}
int dinic (int src,int des)
{
int i,res = 0,top;
int stack[VM]; //stack为栈,存储当前增广路
int cur[VM]; //存储当前点的后继 跟head是一样的
while (BFS(src,des)) //if BFS找到增广路
{
memcpy (cur,head,sizeof (head));
int u = src; //u为当前结点
top = 0;
while (1)
{
if (u == des) //增广路已全部进栈
{
int min = inf,loc ;
for (i = 0;i < top;i ++) //找最小的增广跟并loc记录其在stack中位置
if (min > edge[stack[i]].cap) //以便退回该边继续DFS
{
min = edge[stack[i]].cap;
loc = i;
}
for (i = 0;i < top;i ++) //偶数^1 相当加1 奇数^1相当减1 当正向边 = 0&&路径不合适时,正加负减
{ //偶数是正向边,奇数是负向边,边从0开始
edge[stack[i]].cap -= min;
edge[stack[i]^1].cap += min;
} //将增广路中的所有边修改
res += min;
top = loc;
u = edge[stack[top]].frm; //当前结点修改为最小边的起点
}
for (i = cur[u];i != -1;cur[u] = i = edge[i].next) //找到当前结点对应的下一条边
if (edge[i].cap != 0&&dep[u] + 1 == dep[edge[i].to])//不满足条件时,修改cur值(去掉不合适的占)eg:1-->2 1-->3 1-->4 有边 但只有
break; // 1-->4 这条边满足条件 就把1到2、3的边给去掉
if (cur[u] != -1) //当前结点的下一条边存在
{
stack[top ++] = cur[u]; //把该边放入栈中
u = edge[cur[u]].to; //再从下个点开始找
}
else
{
if (top == 0) //当前结点无未遍历的下一条边且栈空,DFS找不到下一条增广路
break;
dep[u] = -1; //当前结点不在增广路中,剔除该点
u = edge[stack[--top]].frm; //退栈 回朔,继续查找
}
}
}
return res;
} int dir[4][2]={0,1,0,-1,1,0,-1,0};
int x,y;
int main ()///坐标从0或1开始均可 注意别忘记下面的2个初始化
{
int m,n;
int src,des;
int sum=0;
while (scanf ("%d %d",&m,&n)!=EOF)
{
sum=0;
ep = 0;//边的初始化
src =n*m;
des =m*n+1;
memset (head,-1,sizeof(head));///这里初始化
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
{
int mid;
scanf("%d",&mid);
sum+=mid;
//printf("%d\n",i*m+j);
if((i+j)%2==0) addedge(src,i*n+j,mid);
else addedge(i*n+j,des,mid);
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0;k<4;k++)
{
x=i+dir[k][0];
y=j+dir[k][1];
if(x>=0&&x<m&&y>=0&&y<n)
{
if(((x+y)%2)!=((i+j)%2))
{
if((x+y)%2==1)
addedge(i*n+j,x*n+y,inf);
else addedge(x*n+y,i*n+j,inf);
}
}
}
}
}
// printf("sum=%d\n",sum);
int ans = dinic (src,des);
printf ("%d\n",sum-ans);
}
return 0;
}
二分图带权最大独立集 网络流解决 hdu 1569的更多相关文章
- hdu 1569 &1565 (二分图带权最大独立集 - 最小割应用)
要选出一些点,这些点之间没有相邻边且要求权值之和最大,求这个权值 分析:二分图带权最大独立集. 用最大流最小割定理求解.其建图思路是:将所有格点编号,奇数视作X部,偶数视作Y部,建立源点S和汇点T, ...
- BZOJ 3158 千钧一发 (最大流->二分图带权最大独立集)
题面:BZOJ传送门 和方格取数问题很像啊 但这道题不能像网格那样黑白染色构造二分图,所以考虑拆点建出二分图 我们容易找出数之间的互斥关系,在不能同时选的两个点之间连一条流量为$inf$的边 由于我们 ...
- 二分图带权匹配、最佳匹配与KM算法
---------------------以上转自ByVoid神牛博客,并有所省略. [二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和 ...
- 二分图带权匹配 KM算法与费用流模型建立
[二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和最大或最小.而二分图的最佳匹配则一定为完备匹配,在此基础上,才要求匹配的边权值之和最大 ...
- 【二分图带权匹配】Anagram @山东省第九届省赛 A
题目描述 Orz has two strings of the same length: A and B. Now she wants to transform A into an anagram o ...
- poj 2195 二分图带权匹配+最小费用最大流
题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...
- [poj3565] Ants (二分图带权匹配)
传送门 Description 年轻自然主义者比尔在学校研究蚂蚁. 他的蚂蚁以苹果树上苹果为食. 每个蚁群都需要自己的苹果树来养活自己. 比尔有一张坐标为 n 个蚁群和 n 棵苹果树的地图. 他知道蚂 ...
- 二分图带权匹配-Kuhn-Munkres算法模板 [二分图带权匹配]
尴尬...理解不太好T T #include<cstdio> #include<cstring> #include<iostream> #include<al ...
- hdu 1565&hdu 1569(网络流--最小点权值覆盖)
方格取数(1) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
随机推荐
- 关于C++中覆盖,重载,隐藏的一点说明
C++覆盖 重载 隐藏是三个经常容易混淆的概念 这里我们简单总结下: 1.重载的条件(编译时多态) a.同一个类中 b.函数名相同,参数不同(返回值不能作为重载的条件) c.与函数是否为虚函数无关 2 ...
- CentOS6.4安装mplayer
1.准备软件 mplayer官网:http://www.mplayerhq.hu/design7/news.html RPM Fusion网址:http://rpmfusion.org/ EPEL网址 ...
- HDU 1576 A/B(数论)
题目:求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1).数据给出n和b 推导过程 A/B = K K = 9973* ...
- 关于padding
例子 1 padding:10px 5px 15px 20px; 上内边距是 10px 右内边距是 5px 下内边距是 15px 左内边距是 20px 例子 2 padding:10px 5px 15 ...
- IOS开发之语音合成(科大讯飞)详解
1.注册讯飞账号,申请APPID(注意选择IOS平台) 2.加载所需要的类库 3.导入所需要的类库文件头 4.调用申请的APPID以及所需函数,完成语音合成(需要参考官方给出的SDK文件) 详细步 ...
- java与.net比较学习系列(3) 基本数据类型和类型转换
在Java中,数据类型分为两类,一类是基本数据类型,另外一类是引用类型. 而在C#中,数据类型分为三类,分别是基元类型,值类型和引用类型.其中基元类型是.net framework框架中预定义的类型, ...
- C/C++基本数据类型所占字节数
关于这个主要的问题,非常早曾经就非常清楚了,C标准中并没有详细给出规定那个基本类型应该是多少字节数,并且这个也与机器.OS.编译器有关,比方相同是在32bits的操作系统系,VC++的编译器下int类 ...
- 利用Unicorn和Idaemu辅助解决Geekpwn SecretCode
在前面的些文章里,我提到了怎么交叉编译Unicorn-engine,以及在windows上使用Unicorn python bindings进行分析程序.这一次我介绍下如何使用Unicorn-engi ...
- HTML5 本地裁剪图片并上传至服务器(转)
很多情况下用户上传的图片都需要经过裁剪,比如头像啊什么的.但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 ...
- JavaScript禁止用户多次提交方法
[当服务器超载时,会出现提交卡顿的现象,但是用户在操作时,会不停重复点击提交,会造成服务器压力更大.所以我们需要进行限制] [1]将提交按钮禁止 <html> <head> & ...