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;
    }
    
  • 相关阅读:
    NX二次开发-UF_MODL_ask_angle_tolerance获取建模的角度公差
    NX二次开发-UF_MODL_create_bplane创建有界平面
    NX二次开发-UF_MODL_ask_point_containment获取一个点是在体(面,边)的边界内部,外部,还是边界上
    NX二次开发-UFUN获取相邻面UF_MODL_ask_adjac_faces
    NX二次开发-UFUN链表UF_MODL_create_list等用法
    NX二次开发-UFUN发射线函数UF_MODL_trace_a_ray的用法
    NX二次开发-Ufun C函数例子目录【更新日期2020.7.5】
    NX二次开发-C++time函数计时
    NX二次开发-C++的vector用法
    关于C++里set_intersection(取集合交集)、set_union(取集合并集)、set_difference(取集合差集)等函数的使用总结
  • 原文地址:https://www.cnblogs.com/hhlya/p/13559165.html
Copyright © 2011-2022 走看看