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