ZOJ@2874-Paratroopers
ZOJ@2874题意:给一个n*m的网格,网格中某些位有敌人,现在可以在网格边上的x轴或者y轴设置炮台,x炮台可以消灭所在列上的所有敌人,y炮台可以消灭所在行上的所有敌人。现在给定修建x炮台,y炮台的费用,问如何设置炮台,使得消灭所有敌人总费用最少(总费用为设置炮台费用之积)。
解法:最大流。首先对炮台费用求对数,使得总费用之积转化为之和。建图:从源点连有向边到x轴,边的容量为在该处设置炮台的费用;y轴上的点连有向边到汇点,边容量为在该点设置炮台的费用;如果网格中点(x,y)处有敌人,则从x处连边到y,边的容量设置为无穷大。
Code
//
2389416 2011-01-19 19:57:39 Accepted 2874 C++ 40 352 redsea
#include < cstdio >
#include < algorithm >
#include < vector >
#include < cmath >
using namespace std;
#define MAXN 105
#define inf 1000000000.00
double map[MAXN][MAXN];
double flow[MAXN][MAXN];
double max_flow( int n, double mat[][MAXN], int source, int sink, double flow[][MAXN]){
int pre[MAXN],que[MAXN],p,q,t,i,j;
double d[MAXN];
double tmp;
if (source == sink) return inf;
for (i = 0 ;i < n;i ++ )
for (j = 0 ;j < n;flow[i][j ++ ] = 0 );
for (;;){
for (i = 0 ;i < n;pre[i ++ ] = 0 );
pre[t = source] = source + 1 ,d[t] = inf;
for (p = q = 0 ;p <= q &&! pre[sink];t = que[p ++ ])
for (i = 0 ;i < n;i ++ )
if ( ! pre[i] && (tmp = mat[t][i] - flow[t][i]))
pre[que[q ++ ] = i] = t + 1 ,d[i] = d[t] < tmp ? d[t]:tmp;
else if ( ! pre[i] && (tmp = flow[i][t]))
pre[que[q ++ ] = i] =- t - 1 ,d[i] = d[t] < tmp ? d[t]:tmp;
if ( ! pre[sink]) break ;
for (i = sink;i != source;)
if (pre[i] > 0 )
flow[pre[i] - 1 ][i] += d[sink],i = pre[i] - 1 ;
else
flow[i][ - pre[i] - 1 ] -= d[sink],i =- pre[i] - 1 ;
}
tmp = 0 ;
for (i = 0 ;i < n;tmp += flow[source][i ++ ]);
return tmp;
}
int main()
{
int T, n, m, l, s, t;
double x;
scanf( " %d " , & T);
while (T -- ){
scanf( " %d%d%d " , & m, & n, & l);
s = 0 ;
t = m + n + 1 ;
for ( int i = 0 ; i < n + m + 2 ; i ++ )
for ( int j = 0 ; j < n + m + 2 ; j ++ )
map[i][j] = 0 ;
for ( int i = 1 ; i <= m; i ++ ){
scanf( " %lf " , & x);
map[s][i] = log10(x);
}
for ( int i = m + 1 ; i <= n + m; i ++ ){
scanf( " %lf " , & x);
map[i][t] = log10(x);
}
for ( int i = 0 ; i < l; i ++ ){
int sx, sy;
scanf( " %d%d " , & sx, & sy);
map[sx][m + sy] = 10 ;
}
printf( " %.4lf\n " , pow( 10.0 , max_flow(n + m + 2 ,map,s,t,flow)));
}
return 0 ;
}
#include < cstdio >
#include < algorithm >
#include < vector >
#include < cmath >
using namespace std;
#define MAXN 105
#define inf 1000000000.00
double map[MAXN][MAXN];
double flow[MAXN][MAXN];
double max_flow( int n, double mat[][MAXN], int source, int sink, double flow[][MAXN]){
int pre[MAXN],que[MAXN],p,q,t,i,j;
double d[MAXN];
double tmp;
if (source == sink) return inf;
for (i = 0 ;i < n;i ++ )
for (j = 0 ;j < n;flow[i][j ++ ] = 0 );
for (;;){
for (i = 0 ;i < n;pre[i ++ ] = 0 );
pre[t = source] = source + 1 ,d[t] = inf;
for (p = q = 0 ;p <= q &&! pre[sink];t = que[p ++ ])
for (i = 0 ;i < n;i ++ )
if ( ! pre[i] && (tmp = mat[t][i] - flow[t][i]))
pre[que[q ++ ] = i] = t + 1 ,d[i] = d[t] < tmp ? d[t]:tmp;
else if ( ! pre[i] && (tmp = flow[i][t]))
pre[que[q ++ ] = i] =- t - 1 ,d[i] = d[t] < tmp ? d[t]:tmp;
if ( ! pre[sink]) break ;
for (i = sink;i != source;)
if (pre[i] > 0 )
flow[pre[i] - 1 ][i] += d[sink],i = pre[i] - 1 ;
else
flow[i][ - pre[i] - 1 ] -= d[sink],i =- pre[i] - 1 ;
}
tmp = 0 ;
for (i = 0 ;i < n;tmp += flow[source][i ++ ]);
return tmp;
}
int main()
{
int T, n, m, l, s, t;
double x;
scanf( " %d " , & T);
while (T -- ){
scanf( " %d%d%d " , & m, & n, & l);
s = 0 ;
t = m + n + 1 ;
for ( int i = 0 ; i < n + m + 2 ; i ++ )
for ( int j = 0 ; j < n + m + 2 ; j ++ )
map[i][j] = 0 ;
for ( int i = 1 ; i <= m; i ++ ){
scanf( " %lf " , & x);
map[s][i] = log10(x);
}
for ( int i = m + 1 ; i <= n + m; i ++ ){
scanf( " %lf " , & x);
map[i][t] = log10(x);
}
for ( int i = 0 ; i < l; i ++ ){
int sx, sy;
scanf( " %d%d " , & sx, & sy);
map[sx][m + sy] = 10 ;
}
printf( " %.4lf\n " , pow( 10.0 , max_flow(n + m + 2 ,map,s,t,flow)));
}
return 0 ;
}