网络流/二分图最小点权覆盖


  sigh……这题……TLE&RE了好几发

  建一个二分图,左边的每个结点代表行,右边的代表列,如果在(i,j)这个位置有一个外星人,那么我们就连一条边 (左 i ->右 j),这样的话,求一个二分图最小点权覆盖即可。

  为什么这样建图是对的?大家学过二分图应该知道点覆盖是啥吧……(至少学过最小点覆盖=最大匹配吧?)那么我们选了某一个点,比如我们选了左边的第 i 个点,这就表示我们在第 i 行建了一座激光炮,它能打到的外星人就是这个点连出去的所有边!也就是说对于每个外星人(每条边),它被打死(边被覆盖)当且仅当它所在行或列至少有一个方向有激光炮(它连接的两个端点至少有一个被选中),那么现在应该明白了吧= =我们就是要选出权值和最小的一组点,使得所有边都被覆盖。这个用网络流来做比较方便……(其实是我不会别的做法……)

  那么我们现在知道了这是一个二分图的模型,那么怎么建网络流的图呢?对于每个左边的顶点,我们连s->i,w=r[i],右边顶点连汇点t,边权(流量)同理。然后对于二分图中的边我们连(左->右,流量为INF),跑一个最大流(最小割)。(割掉某条边就表示选这个点,边权为INF表示不割它)

  看到这里你可能会问,这样做是不对的吧?样例都过不了的……

  其实……一开始我由于英语没学好……“product”的意思是乘积!!!也就是所有建造的激光炮的权值之积……sigh

  辣么怎么算积的最大值呢?网络流不是只能算和的最大值吗?下面就是见证奇迹的时刻:对所有的权值取log,然后对最终答案取exp!这样就华丽丽地将求乘积最大转化为了求和最大。

  

Trick:这题是取了log的边权……所以在用Dinic增广的时候边界判定需要小心小心再小心。对于double类型的最大流我参考网上的代码重新写了一个模板……

之前在【当前结点是否无法再继续增广(dfs时)】这个地方蛋疼了好久……因为边界处理的不好各种TLE

然后是边集开小了……500×2的RE,500×3的AC……

 Source Code
Problem: User: sdfzyhy
Memory: 760K Time: 0MS
Language: G++ Result: Accepted Source Code //POJ 3308
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,M=,INF=;
const double eps=1e-;
typedef long long LL;
/******************tamplate*********************/ int n,m,l;
double r[N],c[N];
struct edge{
int from,to;
double cap,flow;
};
struct Net{
edge E[M*];
int head[N],next[M*],cnt;
int Q[N];
int s,t,d[N],cur[N];
inline void add(int from,int to,double cap){
E[++cnt]=(edge){from,to,cap,};
next[cnt]=head[from];
head[from]=cnt;
E[++cnt]=(edge){to,from,,};
next[cnt]=head[to];
head[to]=cnt;
}
inline void init(){
cnt=;
n=getint();m=getint();l=getint();
s=; t=n+m+;
F(i,s,t) head[i]=;
F(i,,n){
scanf("%lf",&r[i]);
add(s,i,log(r[i]));
}
F(i,,m){
scanf("%lf",&c[i]);
add(i+n,t,log(c[i]));
}
int x,y;
F(i,,l){
x=getint(); y=getint();
add(x,y+n,INF);
}
}
bool mklevel(){
memset(d,-,sizeof d);
d[s]=;
int l=,r=-;
Q[++r]=s;
while(l<=r){
int x=Q[l++];
for(int i=head[x];i;i=next[i]){
edge&e=E[i];
if (d[e.to]==- && e.cap>e.flow){
d[e.to]=d[x]+;
Q[++r]=(e.to);
}
}
}
return d[t]!=-;
}
double dfs(int x,double a){
if (x==t) return a;
double flow=;
for(int &i=cur[x];i && flow<a;i=next[i]){
edge&e=E[i];
if (e.cap-e.flow> && d[e.to]==d[x]+){
double f=dfs(e.to,min(a-flow,e.cap-e.flow));
flow+=f;
e.flow+=f;
E[i^].flow-=f;
}
}
if (!flow) d[x]=-;
return flow;
}
double Dinic(){
double flow=;
while(mklevel()){
F(i,s,t) cur[i]=head[i];
flow+=dfs(s,INF);
}
return flow;
}
}G1; int main(){
#ifndef ONLINE_JUDGE
freopen("3308.in","r",stdin);
freopen("3308.out","w",stdout);
#endif
int T=getint();
while(T--){
G1.init();
printf("%.4f\n",exp(G1.Dinic()));
}
return ;
}

【POJ】【3308】Paratroopers的更多相关文章

  1. 【 POJ - 1204 Word Puzzles】(Trie+爆搜|AC自动机)

    Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10782 Accepted: 4076 Special ...

  2. 【POJ 1459 power network】

    不可以理解的是,测评站上的0ms是怎么搞出来的. 这一题在建立超级源点和超级汇点后就变得温和可爱了.其实它本身就温和可爱.对比了能够找到的题解: (1)艾德蒙·卡普算法(2)迪尼克算法(3)改进版艾德 ...

  3. 【POJ 2728 Desert King】

    Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 27109Accepted: 7527 Description David the ...

  4. 【POJ 2976 Dropping tests】

    Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 13849Accepted: 4851 Description In a certa ...

  5. 【POJ 3080 Blue Jeans】

    Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 19026Accepted: 8466 Description The Genogr ...

  6. 【POJ各种模板汇总】(写在逆风省选前)(不断更新中)

    1.POJ1258 水水的prim……不过poj上硬是没过,wikioi上的原题却过了 #include<cstring> #include<algorithm> #inclu ...

  7. 【POJ 3669 Meteor Shower】简单BFS

    流星雨撞击地球(平面直角坐标第一象限),问到达安全地带的最少时间. 对于每颗流星雨i,在ti时刻撞击(xi,yi)点,同时导致(xi,yi)和上下左右相邻的点在ti以后的时刻(包括t)不能再经过(被封 ...

  8. 【POJ 2823 Sliding Window】 单调队列

    题目大意:给n个数,一个长度为k(k<n)的闭区间从0滑动到n,求滑动中区间的最大值序列和最小值序列. 最大值和最小值是类似的,在此以最大值为例分析. 数据结构要求:能保存最多k个元素,快速取得 ...

  9. 【POJ 2406 Power Strings】

    Time Limit: 3000MSMemory Limit: 65536K Description Given two strings a and b we define a*b to be the ...

  10. bzoj 2295: 【POJ Challenge】我爱你啊

    2295: [POJ Challenge]我爱你啊 Time Limit: 1 Sec  Memory Limit: 128 MB Description ftiasch是个十分受女生欢迎的同学,所以 ...

随机推荐

  1. Javascript获取URL地址变量参数值的方法

    今天碰到在做一个动态页面的时候,需要用到 URL 的参数值来作判断,从而决定某一块内容在当前页面是否显示.例如exampe.html?parm1=xxx&parm2=xxx&parm3 ...

  2. BeanFactory容器的设计原理

    XmlBeanFactory设计的类继承关系 1.BeanFactory接口提供了使用IoC容器的规范.在这个基础上,Spring还提供了符合这个IoC容器接口的一系列容器的实现供开发人员使用. 2. ...

  3. 关联表映射 Association Table Mapping

    把关联保存为一个表,存储关联表的外键 在对象中,使用集合作为域值,来处理多值域. 而在DB中,只能有单值域. 外键映射的核心,是在关联关系的单值端使用外键来维持联系. 而在多对多的关联关系中,已经不存 ...

  4. JAVA设计模式(DESIGN PATTERNS IN JAVA)读书摘要 第1部分接口型模式——第4章 外观(Facade)模式

    外观模式就类似于一个工具包,一个类对应一个功能. 外观模式的意图是为子系统提供一个接口,便于它的使用. 书中给出的例子是画一个哑弹的飞行路径, 初始的类的设计是这样的,看下图, ShowFlight类 ...

  5. Python单元测试——深入理解unittest (转)

    单元测试的重要性就不多说了,可恶的是Python中 有太多的单元测试框架和工具,什么unittest, testtools, subunit, coverage, testrepository, no ...

  6. ADO.NET笔记——调用存储过程

    相关知识: 在ADO.NET访问SQL Server时,鼓励使用存储过程取代常规的SQL语句. 存储过程有下列优点: 存储过程中的SQL语句将会经过预先的解析和编译,然后存放在数据库服务器上行.调用的 ...

  7. 通信协议之HTTP,UDP,TCP协议

    1.UDP,TCP,HTTP之间的关系 tcp/ip是个协议组,它可以分为4个层次,即网路接口层,网络层,传输层,以及应用层, 在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协 ...

  8. mongodb 3.x WiredTiger存储优化测试

    http://pan.baidu.com/s/1sk8zekX 总结:1.使用WiredTiger引擎压缩比例约是MMAP引擎的12倍,2.从时间上看,此次测试100个线程并发,mongodb 3.2 ...

  9. CentOS设置服务开机启动的方法

    CentOS设置服务开机启动的两种方法 1.利用 chkconfig 来配置启动级别在CentOS或者RedHat其他系统下,如果是后面安装的服务,如httpd.mysqld.postfix等,安装后 ...

  10. PHP 登录完成后如何跳转上一访问页面

    访问网站页面时,有的页面需要授权才能访问,这时候就会要求用户登录,跳转到登录页面login.php,怎么实现登录后返回到刚才访问的页面 项目需求 访问网站页面时,有的页面需要授权才能访问,这时候就会要 ...