[BZOJ 1070] 修车
Link:
Solution:
关键难处在于后加入的车的等待时间受到前面加入车的影响
但将式子同类项合并后发现:$W=n*a_1+(n-1)*a_2...+a_n$
这样就可以将原来的一个人拆成$n$个人,分别表示处理倒数第$i$个车的决策,代价为$i*w$
这样每个车就能独立决策,同时也能保证是最优解
Code:
#include <bits/stdc++.h> using namespace std; #define X first #define Y second typedef long long ll; typedef pair<int,int> P; const int MAXN=1e5+10,INF=1<<30; int n,m,x; namespace mcmf { struct edge {int to,cap,cost,rev;}; vector<edge> a[MAXN]; int S,T,h[MAXN],dist[MAXN],preV[MAXN],preE[MAXN],maxf,minc; void add_edge(int from,int to,int cap,int cost) { a[from].push_back(edge{to,cap,cost,a[to].size()}); a[to].push_back(edge{from,0,-cost,a[from].size()-1}); } void min_cost_flow(int f) { while(f>0) { priority_queue<P,vector<P>,greater<P> > que; fill(dist,dist+T+1,INF); dist[S]=0;que.push(P(0,S)); while(!que.empty()) { P t=que.top();que.pop(); int v=t.Y;if(dist[v]<t.X) continue; for(int i=0;i<a[v].size();i++) { edge &e=a[v][i]; if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]) dist[e.to]=dist[v]+e.cost+h[v]-h[e.to], preV[e.to]=v,preE[e.to]=i,que.push(P(dist[e.to],e.to)); } } if(dist[T]==INF) break; for(int i=1;i<=T;i++) h[i]+=dist[i]; int d=f; for(int i=T;i!=S;i=preV[i]) d=min(d,a[preV[i]][preE[i]].cap); f-=d;minc+=d*h[T];maxf+=d; for(int i=T;i!=S;i=preV[i]) { edge &e=a[preV[i]][preE[i]]; e.cap-=d,a[i][e.rev].cap+=d; } } } } using namespace mcmf; int main() { scanf("%d%d",&n,&m); S=0;T=n*m+m+1; for(int i=1;i<=m;i++) add_edge(S,i,1,0); for(int i=1;i<=n*m;i++) add_edge(m+i,T,1,0); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) { scanf("%d",&x); for(int k=1;k<=m;k++) add_edge(i,m+(j-1)*m+k,1,k*x); } min_cost_flow(INF); printf("%.2lf",(double)minc/m); return 0; }