hihocoder-1389&&2016北京网赛07 Sewage Treatment(二分+网络流)

Posted LittlePointer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihocoder-1389&&2016北京网赛07 Sewage Treatment(二分+网络流)相关的知识,希望对你有一定的参考价值。

题目链接:

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


题意:

给出n个工厂,每个工厂的坐标和每天产生的污水量,再给m个pku,现在要求f=u*sqrt(r)的最小值,要求所有的污水都处理完;
只有工厂的与pku的距离<=r时这个工厂的污水才能给pku处理,而且给的量是任意的,而且所有的u和r是一样的;

思路:

枚举所有的距离,然后二分u,建图的时候源点s到所有的工厂连边,容量为每天产生的污水量,所有的pku到汇点连边,容量为u,然后相距<=r的pku与工厂连边,容量无穷;
跑最大流看是否==sum;
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#include <stack>
#include <map>
  
using namespace std;
  
#define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
  
typedef  long long LL;
  
template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<‘0‘||CH>‘9‘;F= CH==‘-‘,CH=getchar());
    for(num=0;CH>=‘0‘&&CH<=‘9‘;num=num*10+CH-‘0‘,CH=getchar());
    F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
    if(!p) { puts("0"); return; }
    while(p) stk[++ tp] = p%10, p/=10;
    while(tp) putchar(stk[tp--] + ‘0‘);
    putchar(‘\n‘);
}
  
const LL mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=(1<<20)+10;
const int maxn=205;
const double eps=1e-12;

struct Edge
{
    int from,to,cap,flow;
};
vector<Edge>edge;
vector<int>G[maxn];
bool vis[maxn];
int cur[maxn],n,m,fn,s,t,d[maxn];
int dis[210][210];
int x[maxn],y[maxn],fs[maxn],sum,lower,upper,cnt;
double ans;
struct po
{
    int from,to,dis;
}a[105*105];
int cmp(po u,po v)
{
    return u.dis<v.dis;
}
inline void add_edge(int from,int to,int cap)
{
    edge.push_back((Edge){from,to,cap,0});
    edge.push_back((Edge){to,from,0,0});
    m=edge.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
}
bool bfs()
{
    mst(vis,0);
    queue<int>Q;
    Q.push(s);
    d[s]=0;
    vis[s]=1;
    while(!Q.empty())
    {
        int x=Q.front();Q.pop();
        int len=G[x].size();
        for(int i=0;i<len;i++)
        {
            Edge& e=edge[G[x][i]];
            if(!vis[e.to]&&e.cap>e.flow)
            {
                vis[e.to]=1;
                d[e.to]=d[x]+1;
                Q.push(e.to);
            }
        }
    }
    return vis[t];
}

int dfs(int x,int a)
{
    if(x==t||a==0)return a;
    int flow=0,f,len=G[x].size();
    for(int& i=cur[x];i<len;i++)
    {
        Edge& e=edge[G[x][i]];
        if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
        {
            e.flow+=f;
            edge[G[x][i]^1].flow-=f;
            flow+=f;
            a-=f;
            if(a==0)break;
        }
    }
    return flow;
}

int maxflow()
{
    int flow=0;
    while(bfs())
    {
        mst(cur,0);
        flow+=dfs(s,inf);
    }
    return flow;
}
inline void Init(int k,int hi)
{
    edge.clear();
    for(int i=0;i<=t;i++)G[i].clear();
    for(int i=1;i<=k;i++)
    {
        add_edge(a[i].from,a[i].to,inf);
    }
    for(int i=k+1;i<=cnt;i++)
    {
        if(a[i].dis>a[k].dis)break;
        add_edge(a[i].from,a[i].to,inf);
    }
    for(int i=1;i<=n;i++)add_edge(s,i,fs[i]);
    for(int i=n+1;i<=n+fn;i++)add_edge(i,t,hi);
}
inline int check(int k,int flow)
{
    Init(k,flow);
    int ans=maxflow();
    if(ans==sum)return 1;
    return 0;
}
double solve(int k)
{
    double dist=sqrt(sqrt(a[k].dis*1.0));
    int l=lower,r=min(upper,(int)(ceil(ans/dist)));
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(check(k,mid))r=mid;
        else l=mid+1;
    }
    upper=r;
    return dist*r;
}
int main()
{
    while(1)
    {
        read(n);read(fn);
        if(!n&&!fn)break;
        sum=0;
        for(int i=1;i<=n;i++)
        {
            read(x[i]);read(y[i]);read(fs[i]);
            sum=sum+fs[i];
        }
        for(int i=n+1;i<=n+fn;i++)
        {
           read(x[i]);read(y[i]);
        }
        cnt=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=n+1;j<=n+fn;j++)
            {
                int dist=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
                a[++cnt].from=i;
                a[cnt].to=j;
                a[cnt].dis=dist;
            }
        }
        sort(a+1,a+cnt+1,cmp);
        a[0].dis=-1;
        s=0,t=n+fn+1;
        ans=inf;
        lower=(sum+fn-1)/fn,upper=1e4;
        for(int i=1;i<=cnt;i++)
        {
            if(a[i].dis==a[i-1].dis)continue;
            double temp=solve(i);
            ans=min(temp,ans);
        }
        printf("%.0lf\n",ans);
    }
    return 0;
}

  



以上是关于hihocoder-1389&&2016北京网赛07 Sewage Treatment(二分+网络流)的主要内容,如果未能解决你的问题,请参考以下文章

&&&&数组去重方法总结&&&&&

谁能解释一下((a == 1 && a == 2 && a == 3)== true)?

要求的参考折叠规则的简明解释:(1) A& & -> A& , (2) A& && -> & , (3) && &a

(a==1 && a==2 && a==3) 在Java中可以评估为真吗?

(a ==1 && a== 2 && a==3) 有可能是 true 吗?

为啥 C# 中的 1 && 2 为假?