zoukankan      html  css  js  c++  java
  • 2020杭电多校第二场 New Equipments(费用流)

    题目

    roblem Description
    Little Q's factory recently purchased m pieces of new equipment, labeled by 1,2,…,m.

    There are n workers in the factory, labeled by 1,2,…,n. Each worker can be assigned to no more than one piece of equipment, and no piece of equipment can be assigned to multiple workers. If Little Q assigns the i-th worker to the j-th piece of equipment, he will need to pay ai×j2+bi×j+ci dollars.

    Now please for every k (1≤k≤n) find k pairs of workers and pieces of equipment, then assign workers to these pieces of equipment, such that the total cost for these k workers is minimized.

    Input
    The first line of the input contains a single integer T (1≤T≤10), the number of test cases.

    For each case, the first line of the input contains two integers n and m (1≤n≤50, n≤m≤108), denoting the number of workers and the number of pieces of equipment.

    Each of the following n lines contains three integers ai,bi and ci (1≤ai≤10, −108≤bi≤108, 0≤ci≤1016, b2i≤4aici), denoting a worker.

    Output
    For each test case, output a single line containing n integers, the k-th (1≤k≤n) of which denoting the minimum possible total cost for k pairs of workers and pieces of equipment.

    Sample Input
    1
    3 5
    2 3 10
    2 -3 10
    1 -1 4

    Sample Output
    4 15 37

    思路

    每个人都会对应一个函数,我们有n个人,但是一个机器只能给一个人,那么我们要费用尽可能小,所以我们考虑n个函数每个函数去n个点,那么完成匹配的机器必然在这些点里面,由幼儿园学过的二次函数知识,我们可以三分求出最低值已经附近最小的n个值,求完n*n个点后,建图跑最小费用最大流就好了,费用即为答案。

    代码实现

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<unordered_map>
    #include<cmath>
    using namespace std;
    #define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
    #define per(i,n,a) for (int i=n;i>=a;i--)
    #define MT(x,i) memset(x,i,sizeof(x) )
    #define rev(i,start,end) for (int i=start;i<end;i++)
    #define inf 0x3f3f3f3f
    #define mp(x,y) make_pair(x,y)
    #define lowbit(x) (x&-x)
    #define MOD 1000000007
    #define exp 1e-8
    #define N 1000005 
    #define fi first 
    #define se second
    #define pb push_back
    typedef long long ll;
    typedef vector <int> VI;
    typedef pair<int ,int> PII;
    typedef pair<int ,PII> PIII;
    ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
    inline int read() {
        char ch=getchar(); int x=0, f=1;
        while(ch<'0'||ch>'9') {
            if(ch=='-') f=-1;
            ch=getchar();
        } while('0'<=ch&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        } return x*f;
    }
    const int maxn=2e5+10;
    ll s,t,n,m,cnt=1,maxflow,head[maxn];
    ll dis[maxn],vis[maxn],pre[maxn],incf[maxn],ans;
    struct edge {
        ll v,flow,next,cost;
    }e[maxn];
    
    inline void add (ll u,ll v,ll flow,ll cost) {
         e[++cnt].v=v;
         e[cnt].flow=flow;
         e[cnt].next=head[u];
         e[cnt].cost=cost;
         head[u]=cnt;
    }
    
    inline void add_edge (ll u,ll v,ll flow,ll cost) {
        add (u,v,flow,cost);
        add (v,u,0,-cost);
    }
    
    inline void init () {
        MT (head,0);
        MT (pre,-1);
        MT (incf,0);
    
        cnt=1,ans=0;
    }
    
    bool spfa () {
        queue <int> q;
        q.push (s);
        MT (dis,0x3f);
        MT (vis,0);
        dis[s]=0; incf[s]=1ll<<62;
        vis[s]=1; 
        while (q.size ()) {
            int x=q.front (); q.pop ();
            vis[x]=0;
            for (int i=head[x];i;i=e[i].next) {
                int v=e[i].v;
                if (dis[v]>dis[x]+e[i].cost&&e[i].flow) {
                    dis[v]=dis[x]+e[i].cost;
                    incf[v]=min (incf[x],e[i].flow);
                    pre[v]=i;
                    if (!vis[v]) {
                        q.push (v);
                        vis[v]=1;
                    }
                }
            }
        }
        if (dis[t]==0x3f3f3f3f3f3f3f3f) return false;
        return true;
    }
    
    int match[55][55];
    ll a[55],b[55],c[55];
    
    inline void mcmf () {
        int x=t;
        while (x!=s) {
            int i=pre[x];
            e[i].flow-=incf[t];
            e[i^1].flow+=incf[t];
            x=e[i^1].v;
        }
        ans+=incf[t]*dis[t];
        maxflow+=incf[t];
    }
    
    ll f (int i,ll x) {
        return a[i]*x*x+b[i]*x+c[i];
    }
    
    inline void solve () {
        cin>>n>>m;
        init ();
        rep (i,1,n) {
            scanf ("%lld%lld%lld",&a[i],&b[i],&c[i]);
            int l=1,r=m;
            int mid=1;
            while (l<r) {
                int m1= (2*l+r)/3;
                int m2= (l+2*r+2)/3;
                if (f(i,m1)>f(i,m2)) l=m1+1;
                else r=m2-1;
            }
            if (f(i,l)<f(i,r)) mid=l;
            else mid=r;
            l=mid-1,r=mid+1;
            match[i][1]=mid;
            rep (j,2,n) {
               if (f(i,l)<f(i,r)) {
                   if (l>=1&&l<=m) match[i][j]=l--;
                   else match[i][j]=r++;
               }
               else {
                   if (r>=1&&r<=m) match[i][j]=r++;
                   else match[i][j]=l--;
               }
            }
        }
        unordered_map <int,int> mp;
        int tot=0;
        rep (i,1,n) 
         rep (j,1,n) if (!mp[match[i][j]]) mp[match[i][j]]=++tot;
        s=0,t=tot+n+1;
        rep (i,1,n) {
            add_edge (s,i+tot,1,0);
            rep (j,1,n) {
                add_edge (i+tot,mp[match[i][j]],1,f(i,match[i][j]));
            }
        }
        rep (i,1,tot) add_edge (i,t,1,0);
        rep (i,1,n) {
            spfa ();
            mcmf ();
            printf ("%lld",ans);
            printf ("%c",i==n?'
    ':' ');
        }
        return ;
    }
    
    int main () {
        int t;
        cin>>t;
        while (t--) {
            solve ();
        }
        return 0;
    }
    
  • 相关阅读:
    Android笔记
    Scala中apply的用法
    MySQL备忘
    Spring test
    Scala
    Dubbo
    Scala元组
    Scala中None, Nil, Nothing的区别
    java多态与异常处理——动手动脑
    《大道至简》第七八章读后感
  • 原文地址:https://www.cnblogs.com/hhlya/p/13559165.html
Copyright © 2011-2022 走看看