这题很明显的是费用流了,关键是在于建图。其实,网络流的关键也是难点就在于建图。
n个师傅,m个车……
根据题意,需要把每个师傅拆成m个点,每辆车再向这些点连接,再来个超级源点S,超级汇点T即可。
代码很丑……
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int h[1210],d[1210],used[1210],que[100010],last[1210]; int k=1,INF=0x7fffffff,ans=0; inline int read(){ int t=1,num=0; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();} return num*t; } struct edge{ int to,cap,cost,next; }g[60010]; void add(int f,int t,int c1,int c2){ g[++k].next=h[f];h[f]=k;g[k].to=t;g[k].cap=c1;g[k].cost=c2; g[++k].next=h[t];h[t]=k;g[k].to=f;g[k].cap=0;g[k].cost=-c2; } bool spfa(int s,int t){ memset(last,0,sizeof(last)); memset(d,127/3,sizeof(d));INF=d[0]; memset(used,0,sizeof(used)); int tail,head; head=tail=50002; que[head]=s;used[s]=1;d[s]=0; while(head>=tail){ int x=que[tail++]; for(int i=h[x];i;i=g[i].next){ if(g[i].cap&&d[x]+g[i].cost<d[g[i].to]){ d[g[i].to]=d[x]+g[i].cost; last[g[i].to]=i; if(!used[g[i].to]){ if(d[g[i].to]<d[que[tail]])que[--tail]=g[i].to; else que[++head]=g[i].to; used[g[i].to]=1; } } } used[x]=0; } return d[t]!=INF; } void mcf(int t){ int minn=INF; for(int i=last[t];i;i=last[g[i^1].to])minn=min(minn,g[i].cap); for(int i=last[t];i;i=last[g[i^1].to]){ ans+=g[i].cost*minn; g[i].cap-=minn; g[i^1].cap+=minn; } } int main() { int n,m,a[70][10];m=read();n=read(); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=read(); int s=n*m+n+1,t=n*m+n+2; for(int i=1;i<=n;i++)add(s,i,1,0); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=1;k<=n;k++) add(i,j*n+k,1,k*a[i][j]); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) add(i*n+j,t,1,0); while(spfa(s,t))mcf(t); double Ans=(double)(ans); printf("%.2lf",Ans/n); return 0; }
本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。