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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6767

    Problem 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×j^2+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≤10^8), 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≤10^16, bi^2≤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个人,每个人有属性(a_i,b_i,c_i),有m台机器,第(i)个人,匹配第(j)个机器的花费为(a_i imes j^2+b_ij+c_i),问当有1-n个匹配时的最小花费

    emmmm,本来比赛的时候可以写出来的。。。结果演了一波。。。a,b,c的值没用数组保存下来,然后后面还用到了a,b,c,调到绝望QAQ。。。赛后一发AC。。。QAQ

    首先,我们观察,可以用三分来求出每个人在区间([1,m])中的最小匹配值,然后我们向两边拓展,拓展n个匹配,那么我们就可以得到每个人的最小的n个匹配。我们对其建边,跑一波费用流就完事了,每次跑一波残余网络,跑n次残余网络就完事了。

    以下是AC代码:(QAQ博客园又演我,缩进直接跳了好几倍,如果想更好食用代码,请转到我的CSDN博客https://blog.csdn.net/qq_43906000/article/details/107545485

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int mac=1e5+10;
    const ll inf=1e18+7;
    const int INF=1e7+10;
    
    struct edge
    {
        int next, to, f;
        ll w;
    }eg[mac << 1];
    int head[mac], num = 1;
    int pre[mac], vis[mac],flows[mac];
    int s, t, maxflow, flag[mac];
    ll dis[mac];
    
    inline void add(int u, int v, int f, ll w) 
    { 
        eg[++num].to = v; eg[num].next = head[u]; eg[num].f = f; 
        eg[num].w = w; head[u] = num; 
    
        eg[++num].to = u; eg[num].next = head[v]; eg[num].f = 0;
        eg[num].w = -w; head[v] = num;
    }
    void update(int x, int flow)
    {
    	eg[pre[x]].f -= flow;
    	eg[pre[x] ^ 1].f += flow;
    	if (eg[pre[x] ^ 1].to)update(eg[pre[x] ^ 1].to, flow);
    }
    inline ll spfa()
    {
    	memset(vis, 0, sizeof(vis)); 
    	queue<int>q;
    	for (int i = 0; i <= t; i++) dis[i] = inf;
    	flows[s] = INF; dis[s] = 0; q.push(s); vis[s] = 1;
    	while (!q.empty()){
    		int u = q.front(); 
    		q.pop(); vis[u] = 0;
    		for (int i = head[u]; i!=-1; i = eg[i].next){
    			int v = eg[i].to;
    			if (dis[v] > dis[u] + eg[i].w && eg[i].f){
    				dis[v] = dis[u] + eg[i].w;
    				pre[v] = i;
    				flows[v] = min(flows[u], eg[i].f);
    				if (!vis[v]){
    					vis[v] = 1;
    					q.push(v);
    				}
    			}
    		}
    	}
    	if (dis[t] == inf) return inf;
    	maxflow += flows[t];
    	update(t, flows[t]); 
    	return (ll)flows[t] * dis[t];
    }
    ll a[mac],b[mac],c[mac];
    
    ll fff(int i,ll x)
    {
    	return a[i]*x*x+b[i]*x+c[i];
    }
    
    int pot[60][60];
    
    void init()
    {
    	memset(head,-1,sizeof head);
    	memset(flows,0,sizeof flows);
    	memset(pre,0,sizeof pre);
    	num=1;
    }
    
    int main(int argc, char const *argv[])
    {
    	int Cas;
    	scanf ("%d",&Cas);
    	while (Cas--){
    		init();
    		int n,m;
    		scanf ("%d%d",&n,&m);
    		for (int i=1; i<=n; i++){
    			scanf ("%lld%lld%lld",&a[i],&b[i],&c[i]);
    			int l=1,r=m,ans;
    			while (l<r){
    				int mid1=floor(1.0*(2*l+r)/3);
    				int mid2=floor(1.0*(l+2*r+2)/3);
    				if (fff(i,mid1)<fff(i,mid2)){
    					ans=mid1;
    					r=mid2-1;
    				}
    				else {
    					ans=mid2;
    					l=mid1+1;
    				}
    			}
    			int cnt=1;
    			pot[i][cnt]=ans;//三分出的当前区域的最小值点
    			l=ans-1,r=ans+1;//由最优质点向两边拓展n个点
    			while (cnt<n){
    				if (fff(i,l)<fff(i,r)){
    					if (l>=1 && l<=m) {
    						pot[i][++cnt]=l;
    						l--;
    					}
    					else {
    						pot[i][++cnt]=r;
    						r++;
    					}
    				}
    				else {
    					if (r>=1 && r<=m){
    						pot[i][++cnt]=r;
    						r++;
    					}
    					else {
    						pot[i][++cnt]=l;
    						l--;
    					}
    				}
    			}
    		}
    		unordered_map<int,int>q;//给每个点标号
    		int cnt=0;
    		for (int i=1; i<=n; i++){
    			for (int j=1; j<=n; j++){
    				if (!q[pot[i][j]]){
    				 	q[pot[i][j]]=++cnt;
    				}
    			}
    		}
    		s=0;t=cnt+n+1;
    		for (int i=1; i<=n; i++){
    			add(s,cnt+i,1,0);
    			for (int j=1; j<=n; j++){
    				add(cnt+i,q[pot[i][j]],1,fff(i,pot[i][j]));
    			}
    		}
    		for (int i=1; i<=cnt; i++) add(i,t,1,0);
    		ll ans=0;
    		for (int i=1; i<=n; i++){
    			ll x=spfa();//每次跑个残余网络
    			printf("%lld%c",ans+x,i==n?'
    ':' ');
    			ans+=x;
    		}
    	}
    	return 0;
    }
    
    路漫漫兮
  • 相关阅读:
    TP中模型实例化
    PHP中面向对象编程思想的3个特征
    static关键字的新用法
    PHP中与类有关的运算符
    PHP中与类和对象有关的几个系统函数
    PHP中与类有关的几个魔术常量
    PHP与类有关的几个魔术方法
    PHP中类型约束
    PHP对象类型转换
    ubuntu MySQL拒绝远程连接(10061)
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13368156.html
Copyright © 2011-2022 走看看