zoukankan      html  css  js  c++  java
  • [TC-HouseProtection]House Protection

    题目大意:
      一个平面直角坐标系中有给定的$n(nle50)$个红点和$m(mle50)$个蓝点,每个点可以选择画一个半径为$r$(所有的$r$相同)的圆或不画。圆的半径上限为$R(Rle1000)$。且不同颜色的点所画成的圆不能相交,问所有圆面积的和最大是多少?

    思路:
      枚举每一对不同颜色的点,求出所有可能的$r$,显然这样的$r$有$nm$个。
      对于不同颜色的点,若以$r$为半径画出的圆相交,则在这两个点之间连边,题目转化为最大独立集问题。有结论:最大独立集=点数-二分图最大匹配。用Dinic求最大匹配即可。
      对$r$排序,则每次只会增加新的边,只需要在原来的基础上进行增广即可。时间复杂度$O(n^4)$。

      1 #include<cmath>
      2 #include<queue>
      3 #include<vector>
      4 #include<cstring>
      5 #include<climits>
      6 #include<algorithm>
      7 class HouseProtection {
      8     private:
      9         static constexpr int N=50,M=102;
     10         static constexpr double pi=M_PI;
     11         using Point=std::pair<int,int>;
     12         struct Length {
     13             double l;
     14             int u,v;
     15             bool operator < (const Length &rhs) const {
     16                 return l<rhs.l;
     17             }
     18         };
     19         struct Edge {
     20             int from,to,remain,next;
     21         };
     22         Point a[N],b[N];
     23         std::vector<Length> len;
     24         std::vector<Edge> e;
     25         int s,t,lev[M],cur[M],h[M];
     26         double sqr(const double &x) const {
     27             return x*x;
     28         }
     29         double dist(const Point &a,const Point &b) const {
     30             return sqrt(sqr(a.first-b.first)+sqr(a.second-b.second));
     31         }
     32         void add_edge(const int &u,const int &v,const int &w) {
     33             e.push_back({u,v,w,h[u]});
     34             h[u]=e.size()-1;
     35         }
     36         void bfs() {
     37             memset(lev,-1,sizeof lev);
     38             lev[s]=0;
     39             std::queue<int> q;
     40             q.push(s);
     41             while(!q.empty()) {
     42                 const int &x=q.front();
     43                 for(register int i=h[x];~i;i=e[i].next) {
     44                     const int &y=e[i].to,&r=e[i].remain;
     45                     if(r&&!~lev[y]) {
     46                         lev[y]=lev[x]+1;
     47                         q.push(y);
     48                     }
     49                 }
     50                 q.pop();
     51             }
     52         }
     53         int dfs(const int &x,const int &flow) {
     54             if(x==t) return flow;
     55             for(int &i=cur[x];~i;i=e[i].next) {
     56                 const int &y=e[i].to;
     57                 if(e[i].remain&&lev[y]>lev[x]) {
     58                     if(int d=dfs(y,std::min(flow,e[i].remain))) {
     59                         e[i].remain-=d;
     60                         e[i^1].remain+=d;
     61                         return d;
     62                     }
     63                 }
     64             }
     65             return 0;
     66         }
     67         int dinic() {
     68             int maxflow=0;
     69             for(;;) {
     70                 bfs();
     71                 if(!~lev[t]) break;
     72                 memcpy(cur,h,sizeof h);
     73                 while(int flow=dfs(s,INT_MAX)) {
     74                     maxflow+=flow;
     75                 }
     76             }
     77             return maxflow;
     78         }
     79     public:
     80         double safetyFactor(const std::vector<int> &possibleXForBlue,const std::vector<int> &possibleYForBlue,const std::vector<int> &possibleXForRed,const std::vector<int> &possibleYForRed,const int &R) {
     81             memset(h,-1,sizeof h);
     82             const int n=possibleXForBlue.size(),m=possibleXForRed.size();
     83             for(register int i=0;i<n;i++) {
     84                 a[i]={possibleXForBlue[i],possibleYForBlue[i]};
     85             }
     86             for(register int i=0;i<m;i++) {
     87                 b[i]={possibleXForRed[i],possibleYForRed[i]};
     88             }
     89             for(register int i=0;i<n;i++) {
     90                 for(register int j=0;j<m;j++) {
     91                     const double dis=dist(a[i],b[j])/2;
     92                     if(dis<R) len.push_back({dis,i,j});
     93                 }
     94             }
     95             len.push_back({(double)R,-1,-1});
     96             std::sort(len.begin(),len.end());
     97             s=n+m,t=n+m+1;
     98             for(int i=0;i<n;i++) {
     99                 add_edge(s,i,1);
    100                 add_edge(i,s,0);
    101             }
    102             for(int i=0;i<m;i++) {
    103                 add_edge(n+i,t,1);
    104                 add_edge(t,n+i,0);
    105             }
    106             int match=0;
    107             double ans=0;
    108             for(register auto &e:len) {
    109                 match+=dinic();
    110                 ans=std::max(ans,pi*sqr(e.l)*(n+m-match));
    111                 if(e.l<R) {
    112                     add_edge(e.u,n+e.v,1);
    113                     add_edge(n+e.v,e.u,0);
    114                 }
    115             }
    116             return ans;
    117         }
    118 };
  • 相关阅读:
    HDU 4665 Unshuffle DFS找一个可行解
    Servlet生命周期引起的问题
    获取真实Ip地址
    java中return与finally的执行顺序
    理解正则表达式
    抽象类与接口
    java 4种方式读取配置文件 + 修改配置文件
    Java基础语法
    接口多继承
    Java类成员(成员变量和方法)的覆盖与隐藏归纳
  • 原文地址:https://www.cnblogs.com/skylee03/p/9065820.html
Copyright © 2011-2022 走看看