POJ 3308 Paratroopers(最小割/KM)
2012-08-18 17:41
435 查看
题意:一个矩阵,有的方格里有一些敌人,每行或每列都可以安放一架枪,每架枪都有一个花费,而且能消灭他所在的行或列的所有敌人,最后的花费为所有的枪话费的乘积
分析:如果是至少安放几个枪的话,直接就是最小点覆盖;如果求和最小的话,KM就可以解决,但是球的是product 乘积。。。
log(x)就可以转成求和了。。。用最小割或KM均可
dinic代码:
分析:如果是至少安放几个枪的话,直接就是最小点覆盖;如果求和最小的话,KM就可以解决,但是球的是product 乘积。。。
log(x)就可以转成求和了。。。用最小割或KM均可
dinic代码:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<cmath> #define inf 99999 #define nMAX 150 using namespace std; int head[nMAX],level[nMAX],qu[nMAX],s_edge,s,t; struct Edge { int u,v,nxt; double w; }edge[10000]; void addedge(int u,int v,double w) { s_edge++; edge[s_edge].u=u; edge[s_edge].v=v; edge[s_edge].w=w; edge[s_edge].nxt=head[u]; head[u]=s_edge; s_edge++; edge[s_edge].u=v; edge[s_edge].v=u; edge[s_edge].w=0; edge[s_edge].nxt=head[v]; head[v]=s_edge; } double dinic() { int beg,tail,e; double ans=0.0; while(1) { beg=tail=0; qu[tail++]=s; memset(level,-1,sizeof(level)); level[s]=0; while(beg<tail) { int u=qu[beg++]; for(e=head[u];e;e=edge[e].nxt) { int v=edge[e].v; if(level[v]==-1&&edge[e].w>0) { level[v]=level[u]+1; qu[tail++]=v; if(v==t) { beg=tail;break; } } } } if(level[t]==-1)break; beg=s,tail=0; while(1) { if(beg==t) { double flow=(double)inf; int mark; for(int i=0;i<tail;i++) if(edge[qu[i]].w<flow) mark=i,flow=edge[qu[i]].w; for(int i=0;i<tail;i++) { edge[qu[i]].w-=flow; edge[qu[i]^1].w+=flow; } ans+=flow; tail=mark; beg=edge[qu[mark]].u; } for(e=head[beg];e;e=edge[e].nxt) { int v=edge[e].v; if(level[v]==level[beg]+1&&edge[e].w>0) break; } if(e) { qu[tail++]=e; beg=edge[e].v; } else { if(tail==0)break; level[edge[qu[--tail]].v]=-1; beg=edge[qu[tail]].u; } } } return ans; } int main() { int CASE,i,j,k,r,c,num; double w; scanf("%d",&CASE); while(CASE--) { scanf("%d%d%d",&r,&c,&num); s_edge=1; memset(head,0,sizeof(head)); s=0,t=r+c+1; for(i=1;i<=r;i++) { scanf("%lf",&w); addedge(s,i,log(w)); } for(i=1;i<=c;i++) { scanf("%lf",&w); addedge(r+i,t,log(w)); } for(i=1;i<=num;i++) { scanf("%d%d",&j,&k); addedge(j,r+k,double(inf)); } double ans=dinic(); printf("%.4f\n",exp(ans));//my god,G++输出写成f,毛病真多,以后都用f吧 } return 0; }
相关文章推荐
- poj 3308 Paratroopers 二分图最小点权覆盖集+ 最小割+邻接表
- POJ 3308 Paratroopers(最小割+Dinic)
- poj3308 Paratroopers --- 最小点权覆盖->最小割
- POJ 3308 Paratroopers (对数转换+最小点权覆盖)
- 【最小割】POJ-3308 Paratroopers
- poj 3308 Paratroopers 最小割—最大流
- POJ 3308 Paratroopers (对数转换+最小点权覆盖)
- poj 3308 zoj 2874 Paratroopers(最小割)
- POJ 3308 Paratroopers(最小割EK)
- poj3308 Paratroopers --- 最小点权覆盖->最小割
- POJ 3308 Paratroopers(最小割+对数降级)
- POJ 3308 Paratroopers (最小割)
- POJ 3308 Paratroopers(最小点权覆盖+dinic算法)
- POJ 3308 Paratroopers (最小点权覆盖Dinic)
- POJ 3308--Paratroopers【 最小点权覆盖 && 最小割】
- poj 3308 Paratroopers(二分图最小点权覆盖)
- POJ 3308 Paratroopers(最大流最小割の最小点权覆盖)
- POJ 3308 Paratroopers 最小割、最大流
- poj 3308 Paratroopers 最小割 最小点权覆盖
- POJ 3308 Paratroopers(最小点权覆盖)(对数乘转加)