coj 1433 Defend the Bases

来源:互联网 发布:矩阵的秩的所有性质 编辑:程序博客网 时间:2024/06/05 11:59

如果把问题看成一个二分图,左边节点是军队,右边节点是基地。那么二分时间mid,对每一个时间,计算每一个点对(i,j)(i ∈军队,j∈基地)计算需要的移动时间t,如果t < mid,那么就加上这条边。然后对生成的这个图求最大匹配。因为每个节点最多能连接一条匹配边,所以对于基地节点,最多数目的匹配边能连接最多数目的基地节点。当求完最大匹配后,判断是否对基地的每一个点都存在一条匹配边。

#include <iostream>#include<stdio.h>#include<cstring>#include<algorithm>#include<cmath>#define maxn 110using namespace std;int n,m;struct Troop{    double x,y,v;};Troop a[maxn];struct Base{    double x,y;};Base b[maxn];int head[maxn];struct Edge{    int to,next;};Edge e[10010];int cnt_edge;int vis[maxn];int mat[maxn];int match;void init(){    memset(head,-1,sizeof head);    memset(mat,0,sizeof mat);    cnt_edge = 0;    match = 0;}void add_edge(int a,int b){    e[cnt_edge].to = b;    e[cnt_edge].next = head[a];    head[a] = cnt_edge;    cnt_edge++;}bool crosspath(int k){    for(int i = head[k]; i !=-1; i = e[i].next)    {        int j = e[i].to;        if(!vis[j])        {            vis[j] = 1;            if(!mat[j] || crosspath(mat[j]))            {                mat[j] = k;                return true;            }        }    }    return false;}void hungary(){    for(int i = 1; i <= n; i++)    {        memset(vis,0,sizeof vis);        if(crosspath(i))        {            match++;        }    }}double dis(int i,int j){    double temp = sqrt((a[i].x - b[j].x)*(a[i].x - b[j].x) + (a[i].y - b[j].y)*(a[i].y - b[j].y));    return temp/a[i].v;}int main(){    while(scanf("%d %d",&n,&m)!=EOF)    {        for(int i = 1; i <= n; i++)        {            scanf("%lf %lf %lf",&a[i].x,&a[i].y,&a[i].v);        }        for(int i = 1; i <= m; i++)        {            scanf("%lf %lf",&b[i].x,&b[i].y);        }        double low = 0;        double high = 15000;        double mid;        while(high - low > 0.000000001)        {            mid = (low + high)/2;            init();            for(int i = 1; i <= n; i++)                for(int j = 1; j <= m; j++)                {                    if(dis(i,j) < mid)                     {                        add_edge(i,j);                    }                }            hungary();            int flag = 1;            for(int i = 1; i <= m; i++)            {                if(!mat[i])                {                    flag = 0;                    break;                }            }            if(flag) high = mid;            else low = mid;        }        printf("%.10lf\n",mid);    }    return 0;}




0 0
原创粉丝点击