思路:在把乘机转化成对数相加的形式,可以看到要消灭一个外星人,要么在他所在的行上放一把武器,要么在他所在列上放一把武器,因此可以在源点s和行x上连一条log(w)的边,在列和汇点t上连一条log(w)的边,在外星人的坐标x和y+n之间连一条INF的边。因为增广的时候满足流量限制所以会选择最小的代价。
不过还是wa了很久。。原因就是用个g++提交,输出的时候使用了%lf,后来改成%f了还是wa,后来发现关闭了c++和c的输入输出同步,但任然在混用输入。。取消关闭之后就ac了。。。所以建议没事还是不要混用输入输出了
代码如下:
/*************************************************************************
> File Name: c.cpp
> Author: acvcla
> QQ:
> Mail: acvcla@gmail.com
> Created Time: 2014年10月13日 星期一 22时26分17秒
************************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<cstdlib>
#include<ctime>
#include<set>
#include<math.h>
using namespace std;
typedef long long LL;
const int maxn = 5e2 + 30;
const int INF =1e7;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define pb push_back
int n,m,s,t,l;
int d[maxn],cur[maxn];
struct Edge
{
int from,to;
double cap,flow;
};
std::vector<int>G[maxn];
std::vector<Edge>edges;
void init(int n){
for(int i=0;i<=n;i++)G[i].clear();
edges.clear();
}
void addEdge(int u,int v,double w)
{
edges.pb((Edge){u,v,w,0});
edges.pb((Edge){v,u,0.0,0});
int sz=edges.size();
G[u].pb(sz-2);
G[v].pb(sz-1);
}
int bfs(){
memset(d,0,sizeof d);
queue<int>q;
q.push(s);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<G[u].size();i++){
Edge &e=edges[G[u][i]];
if(e.to==s)continue;
if(!d[e.to]&&e.cap>e.flow){
q.push(e.to);
d[e.to]=d[u]+1;
}
}
}
return d[t];
}
double dfs(int u,double a)
{
if(u==t||a==0.0)return a;
double flow=0.0,f=0.0;
for(int &i=cur[u];i<G[u].size();++i){
Edge &e=edges[G[u][i]];
if(d[e.to]==d[u]+1&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0.0){
e.flow+=f;
edges[G[u][i]^1].flow-=f;
flow+=f;
a-=f;
if(a==0.0)break;
}
}
return flow;
}
double Dinic(){
double flow=0;
while(bfs()){
memset(cur,0,sizeof cur);
flow+=dfs(s,INF);
}
return flow;
}
int main(){
//开启关闭同步且混用输入输出wa,注释掉AC
//ios_base::sync_with_stdio(false);
//cin.tie(0);
int T;scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&l);
int u,v;
s=0,t=n+1+m;
init(t);
double w;
for(int i=1;i<=n;i++){
cin>>w;
addEdge(s,i,log(w));
}for(int i=1;i<=m;i++){
cin>>w;
addEdge(n+i,t,log(w));
}
for(int i=1;i<=l;i++){
cin>>u>>v;
addEdge(u,v+n,INF);
}
double ans=Dinic();
printf("%.4f\n",exp(ans));
}
return 0;
}
原文:http://blog.csdn.net/acvcla/article/details/40093915