p2053 [SCOI2007]修车

分析

将m个车拆为n*m个点

相当于将每个车在不同的时段修分成新的车

在第n-i个时段会对之后的车总共造成i*t[i]的贡献

人向车连边然后分别连st即可

代码

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int n,m,s,t,tot,ans,G,pr[100100],d[100100],iq[100100],ano[100100],cnt,id[110][110];
int head[100100],nxt[100100],f[100100],w[100100],to[100100],mf[100100],frm[100100];
inline void add(int x,int y,int z,int c){
    nxt[++cnt]=head[x];head[x]=cnt;to[cnt]=y;f[cnt]=z;w[cnt]=c;frm[cnt]=x;
    nxt[++cnt]=head[y];head[y]=cnt;to[cnt]=x;f[cnt]=0;w[cnt]=-c;frm[cnt]=y;
    ano[cnt]=cnt-1;ano[cnt-1]=cnt;
}
queue<int>q;
inline void work(){
    int i,j,k;
    while(1){
      for(i=0;i<=tot;i++)d[i]=inf,iq[s]=0;
      d[s]=0;
      iq[s]=1;
      q.push(s);
      mf[s]=inf;
      while(!q.empty()){
          int x=q.front();
          q.pop();
          iq[x]=0;
          for(i=head[x];i;i=nxt[i]){
            int y=to[i],z=w[i];
            if(f[i]&&d[y]>d[x]+z){
                d[y]=d[x]+z;
                mf[y]=min(mf[x],f[i]);
                pr[y]=i;
                if(!iq[y])iq[y]=1,q.push(y);
          }
        }
      } 
      if(d[t]>=inf)return;
      int x=pr[t];
      while(x){
          ans+=w[x]*mf[t];
          f[x]-=mf[t];
          f[ano[x]]+=mf[t];
          x=pr[frm[x]];
      }
    }
}
int main(){
    int i,j,k;
    scanf("%d%d",&m,&n);
    s=0,t=1;
    tot=1;
    for(i=1;i<=n;i++)
      for(j=1;j<=m;j++)
        id[i][j]=++tot,add(tot,t,1,0);
    for(i=1;i<=n;i++){
      int x,y;
      x=++tot;
      add(s,x,1,0);
      for(j=1;j<=m;j++){
          scanf("%d",&G);
          for(k=1;k<=m;k++)add(x,id[j][k],1,G*k);
      }
    }
    work();
    printf("%0.2lf
",(double)ans/n);
    return 0;
}
原文地址:https://www.cnblogs.com/yzxverygood/p/11470805.html