题目请戳这里

题目大意:给一个n*m的矩阵,给一些点(ri,ci)表示该点在第ri行第ci列。现在要覆盖所有的点,已知覆盖第i行代价为Ri,覆盖第j列代价为Cj。总代价是累乘的,求最小总代价能覆盖所有的点。

题目分析:最小割。增加一个超级源点和超级汇点,源点到行连边,边权为覆盖行的代价,每列到汇点建边,边权为覆盖该列的代价。对于给定的点对,ri->cj连边,边权无穷大。求一个最小割即可。因为根据割的性质,会将图分成2部分,一部分含源点,一部分含汇点,那么这个割集的边只可能为s->ri、ri->cj、cj->t中的某些边,而ri->cj权是无穷大的,所以不会选这些边,因此割集必在s->ri和cj->t中,那么割集中的边就代表选中要覆盖的行和列,因为要总代价最小,所以求出最小割就是最小总代价。

因为总代价是累乘的,所以要化乘法为加法,取对数。

trick:输出浮点数的时候%.f,%.lf会WA。。。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 105;
const int M = 5500;
const double inf = 100000000.0;
const double eps = 1e-8;
int m,n,l,num;
struct node
{
double c;
int to,next,pre;
}arc[M];
int head[N],sta[N],que[N],cnt[N],dis[N],rpath[N];
void build(int s,int e,double cap)
{
arc[num].to = e;
arc[num].c = cap;
arc[num].next = head[s];
head[s] = num ++;
arc[num - 1].pre = num;
arc[num].pre = num - 1;
arc[num].to = s;
arc[num].c = 0.0;
arc[num].next = head[e];
head[e] = num ++;
}
void re_Bfs()
{
int i,front,rear;
for(i = 0;i <= n + m + 1;i ++)
{
dis[i] = n + m + 2;
cnt[i] = 0;
}
front = rear = 0;
dis[n + m + 1] = 0;
cnt[0] = 1;
que[rear ++] = n + m + 1;
while(front != rear)
{
int u = que[front ++];
for(i = head[u];i != -1;i = arc[i].next)
{
if(arc[arc[i].pre].c < eps || dis[arc[i].to] < n + m + 2)
continue;
dis[arc[i].to] = dis[u] + 1;
cnt[dis[arc[i].to]] ++;
que[rear ++] = arc[i].to;
}
}
}
void ISAP()
{
re_Bfs();
int i,u;
double maxflow = 0.0;
for(i = 0;i <= n + m + 1;i ++)
sta[i] = head[i];
u = 0;
while(dis[0] < n + m + 2)
{
if(u == n + m + 1)
{
double curflow = inf;
for(i = 0;i != m + n + 1;i = arc[sta[i]].to)
curflow = min(curflow,arc[sta[i]].c);
for(i = 0;i != m + n + 1;i = arc[sta[i]].to)
{
arc[sta[i]].c = arc[sta[i]].c - curflow;
arc[arc[sta[i]].pre].c = arc[arc[sta[i]].pre].c + curflow;
}
maxflow = maxflow + curflow;
u = 0;
}
for(i = sta[u];i != -1;i = arc[i].next)
if(arc[i].c > eps && dis[arc[i].to] + 1 == dis[u])
break;
if(i != -1)
{
sta[u] = i;
rpath[arc[i].to] = arc[i].pre;
u = arc[i].to;
}
else
{
if((-- cnt[dis[u]]) == 0)
break;
sta[u] = head[u];
int Min = m + n + 2;
for(i = sta[u];i != -1;i = arc[i].next)
if(arc[i].c > eps)
Min = min(Min,dis[arc[i].to]);
dis[u] = Min + 1;
cnt[dis[u]] ++;
if(u != 0)
u = arc[rpath[u]].to;
}
}
printf("%.4lf\n",pow(10.0,maxflow));
}
int main()
{
int t,i;
int a,b;
double x;
scanf("%d",&t);
while(t --)
{
memset(head,-1,sizeof(head));
scanf("%d%d%d",&n,&m,&l);
for(i = 1;i <= n;i ++)
{
scanf("%lf",&x);
build(0,i,log10(x));
}
for(i = 1;i <= m;i ++)
{
scanf("%lf",&x);
build(n + i,m + n + 1,log10(x));
}
while(l --)
{
scanf("%d%d",&a,&b);
build(a,n + b,inf);
}
ISAP();
}
return 0;
}
//568K 16MS

poj3308Paratroopers(最小割)的更多相关文章

  1. BZOJ 1391: [Ceoi2008]order [最小割]

    1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1509  Solved: 460[Submit][Statu ...

  2. BZOJ-2127-happiness(最小割)

    2127: happiness(题解) Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1806  Solved: 875 Description 高一 ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. BZOJ3438 小M的作物(最小割)

    题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=3438 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为 ...

  5. 最大流-最小割 MAXFLOW-MINCUT ISAP

    简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理 ...

  6. bzoj1412最小割

    太羞耻了,m n写反了(主要是样例n m相等) 建图方法比较高(ji)端(chu),对于可以加栅栏的地方连上1的边,然后求最小割即可 为了让代码优(suo)美(duan),我写了一个check,避免多 ...

  7. 【BZOJ1497】[NOI2006]最大获利 最小割

    裸的最小割,很经典的模型. 建图:要求总收益-总成本最大,那么将每条弧与源点相连,流量为成本,每个收益与汇点相连,流量为收益,然后每条弧与它所能到达的收益相连,流量为inf. 与源点相连的是未被选中的 ...

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

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

  9. CQOI 2016 不同的最小割

    题目大意:一个无向图,求所有点对不同的最小割种类数 最小割最多有n-1个,这n-1个最小割构成一个最小割树 分治法寻找n-1个最小割.对于当前点集X,任选两点为ST做最小割,然后找出与S相连的所有点和 ...

随机推荐

  1. Android中自己定义组件和它的属性

    好长时间没有更新博客了.本来想积累点有深度的东西发,但一直没有找到非常好的点.所以.写一些基础的东西.就当积累吧. Android开发中难免会用到自己定义的组件.以下以ImageButton为例来介绍 ...

  2. Mac经常使用快捷键

    Mac使用快捷键会节省非常多时间.使用最多的键就是shift键  option键 command键的组合了.当然一下略微用得多一点点,还有非常多快捷键没一一列举了 进入指定文件夹的一些快捷键 进入 A ...

  3. Boost源代码学习---shared_ptr.hpp

    最近观看Boost库源代码.Boost功能强大的库,但它的许多源代码,十一细读太费时间,毕竟,还有其他东西要学.所以我决定脱脂感兴趣的章节,他们的设计思路和难以理解的地方记录. shared_ptr是 ...

  4. web前端的发展态势

     以前 作为一个java程序员写的代码主要还是后台的代码,虽然开始的时候前后端都写,但是也是用别人造好的轮子来用,学学html,css,js,jquery,再找一个前端ui框架学学,上手之后我们就可以 ...

  5. Objective-C继承

    继承只是想谈谈在OC中继承的理解:面向对象语言中一个主要的功能就是继承.继承可以使用现在类的所用功能,是对功能的扩展,通过继承创建的新类称为“子类”或“派生类”,被继承的称为“基类”或者“父类”.继承 ...

  6. 16进制的颜色怎么转换为我们iOS所用的RGB颜色

    这个我们就是可以直接宏定义到 我们的工程中,这样我们就可以用我们UI小妹,给我们16进制的颜色表示,愉快的编程了... #define UIColorFromRGB(rgbValue) [UIColo ...

  7. java内存映射文件

    内存映射文件能够让我们创建和修改大文件(大到内存无法读入得文件),对于内存映射文件,我们可以认为是文件已经全部被读入到内存当中,然后当成一个大的数字来访问,简化修改文件的代码. 1.directBuf ...

  8. BZOJ 4305: 数列的GCD( 数论 )

    对于d, 记{ai}中是d的倍数的数的个数为c, 那么有: 直接计算即可,复杂度O(NlogN+MlogM) --------------------------------------------- ...

  9. 200常用JS

    .文本框焦点问题 onBlur:当失去输入焦点后产生该事件 onFocus:当输入获得焦点后,产生该文件 Onchange:当文字值改变时,产生该事件 Onselect:当文字加亮后,产生该文件 &l ...

  10. Hadoop 相关问题

    1.MR Job 输入非常多,启动map 非常多,如何提高MapTask 启动速度(附加条件:集群很空闲,资源多多): 参考答案: a.重写调度器算法,降低时间复杂度 b.Out-of-bound h ...