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 /**************************************************************************************/

 

posted @ 2020-08-02 21:29  ZMWLxh  阅读(270)  评论(0编辑  收藏  举报