Sewage Treatment HihoCoder - 1389 (二分+网络流+剪枝) SAP

版权声明:小白一个,欢迎各位指错。 https://blog.csdn.net/qq_36424540/article/details/82630698

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.

Input

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.

Output

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.

Sample Input

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

Sample Output

17
12

Hint

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.

当时枚举的u, 然后二分的  r, 不出意外的 TLE了

题解还是二分,不过二分的是 半径,而且这个半径不是说所有的点,而是 "有效的点” ,也就是说正好是某些圆的半径的长度,

我们可以预处理出来半径。 然后,建图 ,就是半径小于等于 当前的R的,我们把边都加进去。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=b-1;i>=a;--i)

const int MAXN=210;
const int MAXM=20010;
const int INF=2000000;


struct Fac
{
    Fac(int _x=0,int _y=0,int _v=0,int _id=0)
    {
        x=_x,y=_y,v=_v,id=_id;
    }
    int x,y;
    int v,id;
} fac[MAXN];

struct Pku
{
    int x,y;
    int id;
    Pku(int _x=0,int _y=0,int _id=0)
    {
        x=_x,y=_y,id=_id;
    }
} p[MAXN];

struct EE
{
    EE(int _u=0,int _v=0,int _dis=0){
        u=_u,v=_v,dis=_dis;
    }
    int u,v;
    int dis;
    bool operator<(const EE& b)const
    {
        return dis<b.dis;
    }
}e[MAXN*MAXN];

bool vis[MAXN];

//SAP模板
//注意从1开始,不要去用0 
struct SAP {
	struct Edge {
		int from,to,next,cap,flow;
		Edge(int _from=0,int _to=0,int _cap=0,int _flow=0,int _next=0){
			from=_from,to=_to,next=_next,cap=_cap,flow=_flow;
		} 
	} edge[MAXM]; //注意是 MAXM
	int tol;
	int head[MAXN];
	int gap[MAXN],dep[MAXN],cur[MAXN];
	void init() {
		tol = 0;
		memset(head,-1,sizeof(head));
	}
	void add_edge(int u,int v,int w,int rw = 0) {
		edge[tol]=Edge(u,v,w,0,head[u]);
		head[u] = tol++;
		edge[tol]=Edge(v,u,rw,0,head[v]);
		head[v] = tol++;
	}
	int Q[MAXN];
	void BFS(int start,int end) {
		memset(dep,-1,sizeof(dep));
		memset(gap,0,sizeof(gap));
		gap[0] = 1;
		int front = 0, rear = 0;
		dep[end] = 0;
		Q[rear++] = end;
		while(front != rear) {
			int u = Q[front++];
			for(int i = head[u]; i != -1; i = edge[i].next) {
				int v = edge[i].to;
				if(dep[v] != -1)continue;
				Q[rear++] = v;
				dep[v] = dep[u] + 1;
				gap[dep[v]]++;
			}
		}
	}
 
	int S[MAXN];
	int MaxFlow(int start,int end,int N) {//一共多少个点
		BFS(start,end);
		memcpy(cur,head,sizeof(head));
		int top = 0;
		int u = start;
		int ans = 0;
		while(dep[start] < N) {
			if(u == end) {
				int Min = INF;
				int inser;
 
				for(int i = 0; i < top; i++)
				if(Min > edge[S[i]].cap - edge[S[i]].flow) {
						Min = edge[S[i]].cap - edge[S[i]].flow;
						inser = i;
				}
				for(int i = 0; i < top; i++) {
					edge[S[i]].flow += Min;
					edge[S[i]^1].flow -= Min;
				}
				ans += Min;
				top = inser;
				u = edge[S[top]^1].to;
				continue;
			}
			bool flag = false;
			int v;
			for(int i = cur[u]; i != -1; i = edge[i].next) {
				v = edge[i].to;
				if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) {
					flag = true;
					cur[u] = i;
					break;
				}
			}
			if(flag) {
				S[top++] = cur[u];
				u = v;
				continue;
			}
			int Min = N;
			for(int i = head[u]; i != -1; i = edge[i].next)
				if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) {
					Min = dep[edge[i].to];
					cur[u] = i;
				}
			gap[dep[u]]--;
			if(!gap[dep[u]])return ans;
			dep[u] = Min + 1;
			gap[dep[u]]++;
			if(u != start)u = edge[S[--top]^1].to;
		}
		return ans;
	}
}sap;


int n,m;

int check(int U,int up,int sum){

	sap.init();

	rep(i,1,m+1)sap.add_edge(n+m+1,i,U);
	rep(i,1,n+1)sap.add_edge(m+i,n+m+2,fac[i].v);

	rep(i,0,up)sap.add_edge(e[i].u,m+e[i].v,INF);

	int ans=sap.MaxFlow(n+m+1,n+m+2,n+m+2);

	//printf("U:%d ans:%d\n",U,ans);
	return ans>=sum;
}

int main()
{
   // printf("%.2f\n",20000.0*sqrt(2.0));

    while(scanf("%d %d",&n,&m)==2)
    {
        if(n==0&&m==0)break;

		int sum=0;
        int VVV=0;
        rep(i,1,n+1)
        {
            int x,y;
            int v;
            scanf("%d %d %d",&x,&y,&v);
            fac[i]=Fac(x,y,v,i);
            sum+=v;
            VVV=max(VVV,v);
        }

        rep(i,1,m+1)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            p[i]=Pku(x,y,i);
        }

		int tot=0;
        rep(i,1,m+1)
        {
            rep(j,1,n+1)
            {
                int dx=p[i].x-fac[j].x,dy=p[i].y-fac[j].y;
                int dis=dx*dx+dy*dy;
                e[tot++]=EE(i,j,dis);
            }
        }

        sort(e,e+tot);

        double ans=1e18;

        fill(vis,vis+n+1,0);

        int t=0;
        rep(i,0,tot){
			if(vis[e[i].v])continue;
			vis[e[i].v]=1;
			++t;
			if(t==n){
				t=i;
				break;
			}
        }

        int up=sum;
        rep(i,t,tot){
			int l=sum/n,r=up,mid;

			if((double)l*sqrt(sqrt(e[i].dis))>ans)break;
			
			while(l<r){
				mid=(l+r)>>1;
				if(check(mid,i+1,sum)){
					r=mid;
				}
				else
					l=mid+1;
			}
			//printf("i:%d %.2f r:%d \n",i,e[i].dis,r);
			if(r>up) break;
			up=min(up,r);
			ans=min(ans,sqrt(sqrt(e[i].dis))*up);
        }
        printf("%d\n",int(ans+0.5));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36424540/article/details/82630698
今日推荐