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;
}
原文地址:https://www.cnblogs.com/hhlya/p/13559165.html