标签:P20 strong 一个 max spfa cpp ret CMF pair
建不会建模,直接搬运题解的做法
我么将题意转化一下,求出每一个人对于整体答案的贡献,如果一辆车后面等了 \(k\) 个人,那么这辆车的被等待时间 就是 \(k\times T_{i,j}\) ,然后我们要做的就是为每一辆车分配一个修车工人和一个修车次序,使得任意两个车的修车工人和修车次序不会相同,然后使得总体的贡献最小,这个很费用流
具体来说就是设 \(f_(i,j)\) 表示第 \(i\) 个工人的第 \(j\) 次修理,这样我们把每一辆车 \(x\) 向这一个点连一条边,它的等待时间就是 \(j\times T(i,x)\) ,也就是这条边的费用,然后原点向每一辆车连一条边权为 \(0\) 流量为 \(1\) 的边,每一个工人的每一次修理向汇点连一条边权为 \(0\) 流量为 \(1\) 的边,这样跑一遍费用流,保证了不会有任何两辆车连向同一次修理
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
#define lc rt<<1
#define rc rt<<1|1
#define pb push_back
#define fir first
#define sec second
#define inl inline
#define reg register
using namespace std;
namespace zzc
{
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch==‘-‘) f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 1e3+5;
const int maxm = 1e5+5;
const int inf = 0x3f3f3f3f;
int n,m,st,ed,cnt=1,ans;
int head[maxn],dep[maxn],lst[maxn],siz[maxn],pre[maxn],flow[maxn],dis[maxn];
bool vis[maxn];
queue<int> q;
struct edge
{
int to,nxt,w,cst;
}e[maxm];
void add(int u,int v,int w,int x)
{
e[++cnt].to=v;
e[cnt].w=w;
e[cnt].cst=x;
e[cnt].nxt=head[u];
head[u]=cnt;
}
void add_edge(int u,int v,int w,int x)
{
add(u,v,w,x);add(v,u,0,-x);
}
inl int id(int x,int y)
{
return (x-1)*n+y;
}
bool spfa()
{
for(int i=st;i<=ed;i++) vis[i]=false,flow[i]=inf,dis[i]=inf,pre[i]=-1;
q.push(st);dis[st]=0;
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=false;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].w&&dis[v]>dis[u]+e[i].cst)
{
dis[v]=dis[u]+e[i].cst;
pre[v]=u;
lst[v]=i;
flow[v]=min(flow[u],e[i].w);
if(!vis[v])
{
vis[v]=true;
q.push(v);
}
}
}
}
return pre[ed]!=-1;
}
void MCMF()
{
while(spfa())
{
int now=ed;
ans+=dis[now]*flow[now];
while(now!=st)
{
e[lst[now]].w-=flow[ed];
e[lst[now]^1].w+=flow[ed];
now=pre[now];
}
}
}
void work()
{
int a;
m=read();n=read();st=0;ed=n*m+n+1;
for(int i=1;i<=n;i++) add_edge(st,n*m+i,1,0);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a=read();
for(int k=1;k<=n;k++) add_edge(n*m+i,id(j,k),1,a*k);
}
}
for(int j=1;j<=m;j++) for(int k=1;k<=n;k++) add_edge(id(j,k),ed,1,0);
MCMF();
printf("%.2f\n",1.0*ans/n);
}
}
int main()
{
zzc::work();
return 0;
}
标签:P20 strong 一个 max spfa cpp ret CMF pair
原文地址:https://www.cnblogs.com/youth518/p/14294393.html