题目大意:给定n,m,t1,t2,v分别代表n个导弹发射器,m个物体,发射前的准备时间t1秒,每个导弹发射器发射后经t2分钟才能分社下一个炮弹,速度为v,然后m+n行为m个物体坐标,n行为导弹发射器的坐标.问最后摧毁所有的目标需要的时间是多少。
思路:很明显是最大流的问题。因此还是建图的问题。每个导弹发射器攻击目标可能之前发射了0,1,…m-1次导弹,所以把每个导弹发射器拆成m个,所以共有n*m个发射器。因为每次轰炸一次即可将目标摧毁,所以流量为1 。那么怎么控制求解的时间是最短的呢?这个问题可以转化为求满流并且二分最短的消耗时间。同时将mid作为n*m个导弹发射器和m个目标的联系基础。如果建立他们之间的关系必定是ti[i][j]<=mid.
#include<map>
#include<queue>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<stack>
#include<cstring>
#include<algorithm>
#define LL long long
#define inf 0x3f3f3f3f
#define eps 1e-8
const double PI=acos(-1.0);
using namespace std;
int head[100010],la[100010];
int st,ed,cnt,n,m;
struct node{
int a,b;
}mis[110],aim[110];
double dis[1010][1010],ti[1010][1010];
struct no{
int to,next,w;
}q[100010];
void bu(int a,int b,int w){
q[cnt].to = b;
q[cnt].w = w;
q[cnt].next = head[a];
head[a] = cnt++;
q[cnt].to = a;
q[cnt].w = w;
q[cnt].next = head[b];
head[b] = cnt++;
}
bool bfs(){
memset(la,-1,sizeof(la));
la[st] = 0;
queue<int>Q;
while(!Q.empty())
Q.pop();
Q.push(st);
while(! Q.empty()){
int u=Q.front();
Q.pop();
for(int i = head[u];i != -1; i = q[i].next){
int v = q[i].to;
if(q[i].w && la[v] == -1){
la[v] = la[u] + 1;
Q.push(v);
}
}
}
return la[ed] != -1;
}
int dfs(int x,int f){
if(x == ed || !f){
return f;
}
int a,tmp = 0;
for(int i = head[x]; ~ i ;i = q[i].next){
int u = q[i].to;
if(la[x]+1 == la[u] && q[i].w){
a=dfs(q[i].to,min(q[i].w,f - tmp));
if(a > 0){
q[i].w -= a;
q[i^1].w += a ;
tmp += a;
if(tmp == f){
break;
}
}
}
}
if(!tmp)
la[x] = -1;
return tmp;
}
void creat(double mid){
int i,j;
for(i = 1;i <= m*n ; ++ i){
bu(st,i,1);
}
for(i = 1;i <= m;++ i){
bu(i+m*n,ed,1);
}
for(i = 1;i <= n*m ;++ i){
for(j = 1;j <= m ;++ j){
if(mid >= ti[i][j]){
bu(i,j + n*m,1);
}
}
}
}
double maxflow(){
double ans=0;
while(bfs()){
ans+=dfs(st,inf);
}
return ans;
}
void so(){
double l,r,mid;
l = 0.0,r=2000000.0;
while(r - l >= eps){
mid = (r + l) / 2.0;
cnt=0;
memset(head,-1,sizeof(head));
creat(mid);
if(maxflow() == m){
r = mid;
}
else
l = mid;
}
printf("%.6lf\n",r);
}
int main(){
int i,j,k;double s1,s2,sp;
while(~scanf("%d%d%lf%lf%lf",&n,&m,&s1,&s2,&sp)){
s1 /= 60.0;
st = 0,ed = n * m + m + 1;
for(i = 1;i <= m; ++ i){
scanf("%d%d",&aim[i].a,&aim[i].b);
}
for(i = 1;i <= n;++ i){
scanf("%d%d",&mis[i].a,&mis[i].b);
}
for(i = 1;i <= n;++ i){
for(j = 1;j <= m;++ j){
dis[i][j] = sqrt((mis[i].a-aim[j].a)*(mis[i].a-aim[j].a)+(mis[i].b-aim[j].b)*(mis[i].b-aim[j].b) );
}
}
for(i = 1;i <= n;++ i){
for(k = 1;k <= m ;++ k){
for(j = 1;j <= m; ++j){
ti[(i-1)*m + k][j] = s1 * k +s2*(k-1) + dis[i][j] / sp;
}
}
}
so();
}
return 0;
}