HDU2020多校第二场--New Equipments(费用流+二分最大匹配
题意:http://acm.hdu.edu.cn/showproblem.php?pid=6767
n个人,选机器,每个人有a,b,c,选机器的费用是a*x*x+b*x+c,问选k个人的最小费用
思路:
1 int to[N]; 2 int have[N]; 3 4 int temp[N]; 5 void LS(int n) 6 { 7 int m=0; 8 for(int i=1;i<=n;++i) 9 temp[++m]=to[i]; 10 sort(temp+1,temp+1+m); 11 m=unique(temp+1,temp+1+m)-temp-1; 12 for(int i=1;i<=n;++i) 13 to[i]=lower_bound(temp+1,temp+1+m,to[i])-temp; 14 return ; 15 } 16 int res[N],cnt_res; 17 18 class MCMF 19 { 20 public: 21 int n; 22 struct node 23 { 24 int u,v,f,w,nxt; 25 }edge[N<<2]; 26 int head[N],tot; 27 int h[N],dis[N],PrePoint[N],PreEdge[N]; 28 void Init(int _n) 29 { 30 n=_n; 31 tot=-1; 32 for(int i=0;i<=_n;++i) 33 head[i]=-1,h[i]=0; 34 } 35 void _add(int x,int y,int f,int w)//流量为f,花费为w 36 { 37 ++tot; 38 edge[tot]={x,y,f,w,head[x]}; 39 head[x]=tot; 40 } 41 void Add(int x,int y,int f,int w) 42 { 43 _add(x,y,f,w); 44 _add(y,x,0,-w); 45 } 46 pair<ll,ll> Dij(int S,int T) 47 { 48 int max_flow=0,min_cost=0; 49 while(1) 50 { 51 priority_queue<pair<ll,ll>>q; 52 for(int i=0;i<=n;++i) 53 dis[i]=INF; 54 dis[S]=0; 55 q.push({0,S}); 56 while(!q.empty()) 57 { 58 pair<ll,ll> now=q.top();q.pop(); 59 if(-now.first!=dis[now.second])continue; 60 if(now.second==T)break; 61 for(int i=head[now.second];i!=-1;i=edge[i].nxt) 62 { 63 int nowcost=edge[i].w+h[now.second]-h[edge[i].v]; 64 if(edge[i].f>0&&dis[edge[i].v]>dis[now.second]+nowcost) 65 { 66 dis[edge[i].v]=dis[now.second]+nowcost; 67 q.push({-dis[edge[i].v],edge[i].v}); 68 PrePoint[edge[i].v]=now.second; 69 PreEdge[edge[i].v]=i; 70 } 71 } 72 } 73 if(dis[T]==INF)break; 74 for(int i=0;i<=n;++i)h[i]+=dis[i]; 75 int nowflow=INF; 76 for(int i=T;i!=S;i=PrePoint[i]) 77 nowflow=min(nowflow,edge[PreEdge[i]].f); 78 for(int i=T;i!=S;i=PrePoint[i]) 79 { 80 edge[PreEdge[i]].f-=nowflow; 81 edge[PreEdge[i]^1].f+=nowflow; 82 } 83 max_flow+=nowflow; 84 min_cost+=nowflow*h[T]; 85 res[++cnt_res]=min_cost; 86 } 87 return {max_flow,min_cost}; 88 } 89 }G; 90 91 struct node 92 { 93 int a,b,c; 94 }ren[N]; 95 96 void solve() 97 { 98 int n,m; 99 sc("%lld%lld",&n,&m); 100 int S=n*(2*n+5)+n+5,T=S+1; 101 cnt_res=0; 102 G.Init(T); 103 for(int i=1;i<=n;++i)have[i]=0; 104 int tot=0; 105 for(int I=1;I<=n;++I) 106 { 107 G.Add(S,I,1,0); 108 int a,b,c; 109 sc("%lld%lld%lld",&a,&b,&c); 110 ren[I]={a,b,c}; 111 int mid=-b/(2*a); 112 if(mid<1)mid=1; 113 if(mid>m)mid=m; 114 for(int i=mid,j=1;i>=1&&j<=n;--i,++j) 115 to[++tot]=i,have[I]++; 116 for(int i=mid+1,j=1;i<=m&&j<=n;++i,++j) 117 to[++tot]=i,have[I]++; 118 } 119 LS(tot); 120 int max_=0; 121 for(int i=1;i<=tot;++i)max_=max(max_,to[i]); 122 for(int i=1;i<=max_;++i) 123 G.Add(i+n,T,1,0); 124 tot=0; 125 for(int i=1;i<=n;++i) 126 { 127 for(int j=1;j<=have[i];++j) 128 { 129 ++tot; 130 int pos=temp[to[tot]]; 131 int w=ren[i].a*pos*pos+ren[i].b*pos+ren[i].c; 132 G.Add(i,to[tot]+n,1,w); 133 } 134 } 135 pair<ll,ll> ans=G.Dij(S,T); 136 for(int i=1;i<=n;++i) 137 pr("%lld%c",res[i]," \n"[i==n]); 138 // pr("%lld\n",ans.second); 139 } 140 141 signed main() 142 { 143 int T; 144 sc("%lld",&T); 145 while(T--)solve(); 146 return 0; 147 } 148 149 /**************************************************************************************/