zoukankan      html  css  js  c++  java
  • soj115 御坂网络

    题意:平面上有n个A发射点和m个B发射点,可以选择安置相应A/B装置,装置范围是圆,自取半径(要求都相同且<=Rmax)。异种要求范围不相交。求装置范围之和(不是并!)。

    标程:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=405;
     4 const int inf=0x3f3f3f3f;
     5 typedef long long ll;
     6 int cnt=1,n,m,ans,Rx,xa[N],xb[N],yb[N],ya[N],head[N],Head[N],tot,S,T,dis[N];
     7 ll Ans;
     8 queue<int> q;
     9 bitset<N> f[N];
    10 struct node{int to,next,f;}num[N*N];
    11 struct Node{int d,x,y;Node(){} Node(int A,int B,int C){d=A;x=B;y=C;}}p[N*N];
    12 void add(int x,int y,int w)
    13 {
    14   num[++cnt].to=y;num[cnt].next=head[x];num[cnt].f=w;head[x]=cnt;
    15   num[++cnt].to=x;num[cnt].next=head[y];num[cnt].f=0;head[y]=cnt;
    16   if (!f[x][y]) 
    17     for (int i=1;i<=T;i++) if (f[i][x]&&!f[i][y]) f[i]|=f[y];
    18 }
    19 void init()
    20 {
    21    for (int i=1;i<=T;i++) f[i].reset(),f[i][i]=1;
    22    for (int i=1;i<=T;i++)
    23      for (int j=head[i];j;j=num[j].next)
    24        if (num[j].f) f[i][num[j].to]=1;
    25    for (int i=1;i<=T;i++)
    26      for (int j=1;j<=T;j++) if (f[i][j]) f[i]|=f[j];
    27 }
    28 int bfs()
    29 {
    30   memset(dis,0,sizeof(dis));dis[S]=1;q.push(S);
    31   while (!q.empty())
    32   {
    33     int now=q.front();q.pop();
    34     for (int i=head[now];i;i=num[i].next)
    35       if (num[i].f&&!dis[num[i].to]) dis[num[i].to]=dis[now]+1,q.push(num[i].to);
    36   }
    37   return dis[T];
    38 }
    39 int dfs(int x,int Min)
    40 {
    41   int tmp=Min;
    42   if (x==T||!Min) return Min;
    43   for (int &i=Head[x];i&&tmp;i=num[i].next)
    44     if (dis[num[i].to]==dis[x]+1)
    45     {
    46        int t=dfs(num[i].to,min(tmp,num[i].f));
    47        num[i].f-=t;num[i^1].f+=t;tmp-=t;
    48     }
    49   return Min-tmp;
    50 }
    51 int dinic()
    52 {
    53   if (!f[S][T]) return 0;
    54   int res=0,tmp;
    55   while (bfs())
    56   {
    57     memcpy(Head,head,sizeof(head));
    58     while (tmp=dfs(S,inf)) res+=tmp;
    59   }
    60   init();
    61   return res;
    62 }
    63 int get_dis(int i,int j){return (xa[i]-xb[j])*(xa[i]-xb[j])+(ya[i]-yb[j])*(ya[i]-yb[j]);}
    64 bool cmp(const Node &A,const Node &B){return A.d<B.d;}
    65 int main()
    66 {
    67   scanf("%d%d%d",&n,&m,&Rx);S=n+m+1;T=S+1;
    68   for (int i=1;i<=T;i++) f[i][i]=1;
    69   for (int i=1;i<=n;i++) add(S,i,1);
    70   for (int i=1;i<=m;i++) add(i+n,T,1);
    71   for (int i=1;i<=n;i++) scanf("%d",&xa[i]);
    72   for (int i=1;i<=n;i++) scanf("%d",&ya[i]);
    73   for (int i=1;i<=m;i++) scanf("%d",&xb[i]);
    74   for (int i=1;i<=m;i++) scanf("%d",&yb[i]);
    75   for (int i=1;i<=n;i++)
    76     for (int j=1;j<=m;j++) p[++tot]=Node(get_dis(i,j),i,j);
    77   p[++tot]=Node(Rx*Rx*4,0,0);
    78   sort(p+1,p+tot+1,cmp);
    79   for (int i=0;i<=tot&&p[i].d<=Rx*Rx*4;i++)//从0开始,有可能
    80   {
    81       add(p[i].x,p[i].y+n,1);
    82       if (p[i].d!=p[i+1].d) ans+=dinic(),Ans=max(Ans,min((ll)max(p[i+1].d,p[i].d),Rx*Rx*4ll)*(n+m-ans));//注意取后一个半径进行运算,注意边界!
    83   }
    84   printf("%.4lf
    ",(double)Ans*M_PI*0.25);
    85   return 0;
    86 }

    易错点:1.注意统计圆半径是已连边半径的后一个。因此需要从没有圆冲突的半径开始算。

    2.一开始以为是圆半径不相同。题目又又又看错了啊。可能是太久没写题了。

    题解:枚举半径+网络流匹配+传递闭包优化

    如果某A和某B之间的距离为dis,那么如果取半径>dis/2,该A和该B之间只能取其一。

    枚举关键半径n^2。只能取其一,即求最大独立集。我们想到了可以二分图匹配n^3(而边权为1用dinic可以做到n^2.5)。O(n^4.5)。

    结束。

    用传递闭包在每次网络流结束后统计S到T的可达情况。下一次进去的时候若S->T不可达,那么return 0。这样最多进行n次网络流,bitset优化一下:O(n*(n^3/w+n^2.5))。

  • 相关阅读:
    Linux命令之查看cpu个数_核数_内存总数
    Python文件操作大全,随机删除文件夹内的任意文件
    Python文件操作:同一个文件进行内容替换
    异步请求Python库 grequests的应用和与requests库的响应速度的比较
    查询MySQL某字段相同值得重复数据
    /var/redis/run/redis_6379.pid exists, process is already running or crashed的解决办法
    人工智能----TensorFlow开篇简介
    Centos6.5+Python2.7 +ffmpeg+opencv2自动安装脚本
    决策统计---指标六要素
    大数据应用分类
  • 原文地址:https://www.cnblogs.com/Scx117/p/9065852.html
Copyright © 2011-2022 走看看