链接
https://www.luogu.org/problemnew/show/P2053
大意
有 辆车 个人,不同的人修不同的车时间不相同,先给出他们修它们的时间,求最小平均等待时间
思路
最小平均等待时间=最小总等待时间
把 个工人分成 个人,然后把他们连向汇点,再把车连向源点,容量为1,没有代价
之后把每个人和他们可以修的车连在一起,容量为1,代价为这个人修车的顺序乘时间
之后再跑费用流就好了
代码
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#define M 100000
using namespace std;int f,n,m,s,t,ans1,ans2,u,v,w,g,t1,b[1001][1001];char c;
int read()
{
f=0;
while(c=getchar(),c<=47||c>=58);f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;
return f;
}
struct node{int next,to,w,g;}e[M<<1];
int dis[M],l[M],tot,pos[M];
bool vis[M];
void add(int u,int v,int w,int c)
{
e[tot]={l[u],v,w,c};l[u]=tot++;
e[tot]={l[v],u,0,-c};l[v]=tot++;
return;
}
bool spfa()
{
fill(dis+1,dis+1+t,50234567);
memset(vis,0,sizeof(vis));
queue<int>q;q.push(s);dis[s]=0;vis[s]=true;
while(q.size())
{
int x=q.front();q.pop();vis[x]=true;
for(int i=l[x];~i;i=e[i].next)
{
int y=e[i].to,w=e[i].g;
if(e[i].w&&dis[y]>dis[x]+w)
{
dis[y]=dis[x]+w;
pos[y]=i;
if(!vis[y]) q.push(y),vis[y]=true;
}
}
vis[x]=false;
}
return dis[t]<50234567;
}
void updata()
{
int x=t;
while(x!=s)
{
int i=pos[x];
e[i].w--;
e[i^1].w++;
x=e[i^1].to;
}
ans1++;
ans2+=dis[t];
return;
}
void EK()
{
while(spfa())
updata();return;
}
int main()
{
memset(l,-1,sizeof(l));
m=read();n=read();s=0;t=n*m+n+1;
for(int i=1;i<=n;i++) add(s,m*n+i,1,0);//车连源点
for(int i=1;i<=n*m;i++) add(i,t,1,0);//人连汇点
for(int j=1;j<=n;j++)
for(int i=1,x;i<=m;i++)
{
x=read();
for(int k=1;k<=n;k++) add(n*m+j,~-(i)*n+k,1,k*x);//~-i=i-1,连接这辆车和可以修这辆车的人
}
EK();//跑一遍费用流
printf("%.2lf",1.0*ans2/n);//输出
}