hihoCoder 1389 Sewage Treatment 二分+网络流+优化 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)

Posted Coolxxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihoCoder 1389 Sewage Treatment 二分+网络流+优化 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)相关的知识,希望对你有一定的参考价值。

#1389 : Sewage Treatment

时间限制:2000ms
单点时限:2000ms
内存限制:256MB

描述

After years of suffering, people could not tolerate the pollution in the city any more, and started a long-lasting protest. Eventually, the municipal government made up its mind to deal with the sewage discharged by factories. The government planned to deploy some Pollution-Killer Utilities (PKUs) in order to clean all the sewage, and meanwhile, minimize the total cost.

The city can be approximately considered as a plane. There are n factories discharging sewage. The i-th one is located at (xi, yi), and discharges si units of sewage every day. The government has built m PKUs. The PKUs\' locations are also fixed, and the j-th one is located at (xj, yj). Two features of PKUs are essential, and you will need to find the best choice of them: u is the upper limit of units of sewage that can be cleaned by one PKU every day, and c is the coverage radius of one PKU (which means, only if the distance between the PKU and the factory does not exceed the coverage radius, sewage discharged by this factory can be cleaned by this PKU). Note that all the PKUs share the same u and c. Because of some technical reasons, u has to be a positive integer.

Here is your task. The cost of deploying these PKUs can be weighed by an empirical formula:

f = u×sqrt(c)

You need to calculate the minimum value of f, and guarantee all the sewage is treated.

输入

There are no more than 15 test cases. Each test case starts with a line containing two positive integers n and m (1 <= n, m <= 100), representing the number of factories and PKUs. Then n lines follow, the i-th line contains three integers xi, yi, si (-10000 <= xi, yi <= 10000, 1 <= si <= 100), representing the i-th factory\'s location and the quantity of sewage discharged by it every day. In the next following m lines, the j-th line contains two integers xj, yj (-10000 <= xj, yj <= 10000), representing the j-th PKU\'s location. After each test case there is an empty line. After all the test cases there is a line "0 0", which indicates the end of the input, and should not be processed.

输出

For each test case, output a single line containing a number, which is the minimum value of f. This number should be rounded to an integer.

提示

Test case 1:

When u = 12 and c = 2, f has the minimum value of 12 * sqrt(2) = 16.97 = 17.

Test case 2:

When u = 10, c = sqrt(2), f has the minimum value of 10 * sqrt(sqrt(2)) = 11.89 = 12.

The input guarantees that there is always a valid solution. You may assume that the factories and PKUs are uniformly randomly distributed on the plane.

样例输入
3 1
-1 0 5
2 0 3
0 1 4
0 0

4 2
0 0 4
3 0 5
3 2 3
0 2 6
1 1
2 1

0 0
样例输出
17
12

 

题目链接:

  http://hihocoder.com/problemset/problem/1389

题目大意:

  N个污水厂fac,M个污水处理厂pku(N,M<=100)。每个污水厂坐标(xi,yi),会产生Si的污水。每个污水处理厂坐标(xi,yi),可以处理距离在C范围内的总量为U的污水(一个污水厂能被多个处理厂一起处理)。

  所有污水处理厂的U,C必须保持相同,求在能处理所有污水的情况下 f=U*√C 函数最小值。(U为正整数,C为欧拉距离,坐标范围在[-10000,10000])

题目思路:

  【二分+网络流+优化】

  首先求出每个污水处理厂b[i].from到每个污水厂b[i].to的欧拉距离b[i].dis,从小到大排序,总共N*M条边。设源S 汇T

  枚举C=b[i].dis(确保每个污水厂都和至少一个污水处理厂相连),二分需要的最小的U

  check时将前i条边都加入到网络流的图中,边的容量为无穷大。S到每个污水处理厂连一条容量为U的边,每个污水厂到T连一条容量为Si的边

    然后从S到T跑最大流看是否等于总污水量sum。等于就表明当前U可行,否则当前U不可行。

  光这样做会T,需要优化,二分U的上界为当前可行的最小的U(因为C在不断增大,f只有在U减小的情况下才可能更优),下界为sum/n,表示每个污水处理厂至少处理的均摊量。

  再加一个优化 当前枚举的C和二分下界l算出的函数f已经超过f的最优值时就break(再往后答案不会更优)。

  【我也不知道为什么这样就过了。比赛的时候觉得会T就没写。。结果看了大牛的题解发现真的是这么做。不过比赛的时候优化没想清楚可能还会T】

 

  1 //
  2 //by coolxxx
  3 //#include<bits/stdc++.h>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<string>
  7 #include<iomanip>
  8 #include<map>
  9 #include<stack>
 10 #include<queue>
 11 #include<set>
 12 #include<bitset>
 13 #include<memory.h>
 14 #include<time.h>
 15 #include<stdio.h>
 16 #include<stdlib.h>
 17 #include<string.h>
 18 //#include<stdbool.h>
 19 #include<math.h>
 20 #define min(a,b) ((a)<(b)?(a):(b))
 21 #define max(a,b) ((a)>(b)?(a):(b))
 22 #define abs(a) ((a)>0?(a):(-(a)))
 23 #define lowbit(a) (a&(-a))
 24 #define sqr(a) ((a)*(a))
 25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
 26 #define mem(a,b) memset(a,b,sizeof(a))
 27 #define eps (1e-10)
 28 #define J 10000
 29 #define mod 1000000007
 30 #define MAX 0x7f7f7f7f
 31 #define PI 3.14159265358979323
 32 #pragma comment(linker,"/STACK:1024000000,1024000000")
 33 #define N 204
 34 #define M 20004
 35 using namespace std;
 36 typedef long long LL;
 37 double anss;
 38 LL aans,sum;
 39 int cas,cass;
 40 int n,m,lll,ans;
 41 int C,U,S,T,nn;
 42 int d[N],vd[N],last[N];
 43 int mapp[N][N];
 44 bool mark[N];
 45 struct Point
 46 {
 47     int x,y,qq;
 48 }fac[N],pku[N];
 49 struct Edge
 50 {
 51     int from,to,dis;
 52 }b[M];
 53 struct xxx
 54 {
 55     int from,to,next,q;
 56 }a[M<<1];
 57 bool cmp1(Point aa,Point bb)
 58 {
 59     if(aa.x!=bb.x)return aa.x<bb.x;
 60     return aa.y<bb.y;
 61 }
 62 bool cmp2(Edge aa,Edge bb)
 63 {
 64     return aa.dis<bb.dis;
 65 }
 66 void add(int x,int y,int z)
 67 {
 68     a[++lll].to=y;
 69     a[lll].q=z;
 70     a[lll].next=last[x];
 71     last[x]=lll;
 72 }
 73 int sap(int u,int f)
 74 {
 75     int i,v,tt,asp=0,mix=nn-1;
 76     if(u==T)return f;
 77     for(i=last[u];i!=0;i=a[i].next)
 78     {
 79         v=a[i].to;
 80         if(a[i].q>0)
 81         {
 82             if(d[u]==d[v]+1)
 83             {
 84                 tt=sap(v,min(f-asp,a[i].q));
 85                 asp+=tt;
 86                 a[i].q-=tt;
 87                 a[i^1].q+=tt;
 88                 if(asp==f || d[S]==nn)
 89                     return asp;
 90             }
 91             mix=min(mix,d[v]);
 92         }
 93     }
 94     if(asp!=0)return asp;
 95     if(!--vd[d[u]])d[S]=nn;
 96     else vd[d[u]=mix+1]++;
 97     return asp;
 98 }
 99 bool check(int u)
100 {
101     int i,f;
102     mem(d,0);mem(vd,0);
103     nn=T;
104     vd[0]=nn;
105     ans=0;
106     while(d[S]<nn)
107     {
108         f=sap(S,MAX);
109         ans+=f;
110     }
111     if(ans==sum)return 1;
112     return 0;
113 }
114 void build(int k,int uu)
115 {
116     int i;
117     mem(last,0);lll=1;
118     for(i=1;i<=m;i++)
119         add(S,i,uu),add(i,S,0);
120     for(i=1;i<=n;i++)
121         add(m+i,T,fac[i].qq),add(T,m+i,0);
122     for(i=1;i<=k;i++)
123         add(b[i].from,b[i].to+m,MAX),add(b[i].to+m,b[i].from,0);
124 }
125 int main()
126 {
127     #ifndef ONLINE_JUDGEW
128 //    freopen("1.txt","r",stdin);
129 //    freopen("2.txt","w",stdout);
130     #endif
131     int i,j,k;
132     int x,y,z,l,r,mid;
133 //    init();
134 //    for(scanf("%d",&cass);cass;cass--)
135 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
136 //    while(~scanf("%s",s))
137     while(~scanf("%d%d",&n,&m))
138     {
139         sum=0;cas=0;anss=1e30;ans=0;
140         mem(mark,0);
141         if(!n && !m)break;
142         for(i=1;i<=n;i++)
143         {
144             scanf("%d%d%d",&fac[i].x,&fac[i].y,&fac[i].qq);
145             sum+=fac[i].qq;
146         }
147         for(i=1;i<=m;i++)
148             scanf("%d%d",&pku[i].x,&pku[i].y);
149         //sort(fac+1,fac+1+n,cmp1);
150         //sort(pku+1,pku+1+m,cmp1);
151         for(i=1;i<=m;i++)
152         {
153             for(j=1;j<=n;j++)
154             {
155                 b[++cas].from=i;
156                 b[cas].to=j;
157                 b[cas].dis=sqr(fac[j].x-pku[i].x)+sqr(fac[j].y-pku[i].y);
158             }
159         }
160         sort(b+1,b+1+cas,cmp2);
161         S=n+m+1,T=n+m+2;
162         for(j=0,k=1;k<=cas;k++)
163         {
164             if(!mark[b[k].to])
165             {
166                 j++,mark[b[k].to]=1;
167                 if(j==n)break;
168             }
169         }
170         U=sum;
171         for(;k<=cas;k++)
172         {
173             C=b[k].dis;
174             l=sum/n,r=U;
175             if((double)l*sqrt(sqrt(C))>anss)break;
176             while(l<r)
177             {
178                 mid=(l+r)>>1;
179                 build(k,mid);
180                 if(check(mid))r=mid;
181                 else l=mid+1;
182             }
183             U=min(U,r);
184             anss=min(anss,U*sqrt(sqrt(C)));
185         }
186         printf("%d\\n",int(anss+0.5));
187     }
188     return 0;
189 }
190 /*
191 //
192 
193 //
194 */
View Code

 

以上是关于hihoCoder 1389 Sewage Treatment 二分+网络流+优化 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)的主要内容,如果未能解决你的问题,请参考以下文章

1389 乘积平均数

算法1389. 按既定顺序创建目标数组(多语言实现)

leetcode1389

codevs 1389 乘积平均数

BUAA1389愤怒的DZY(最大值最小化)

POJ 1389 Area of Simple Polygons 扫描线+线段树面积并