P2053 [SCOI2007]修车(逆向思维分层建图)

得 先 把 题 意 转 化 一 下 , 否 则 无 法 建 图 得先把题意转化一下,否则无法建图 ,

为 啥 没 办 法 建 图 ? 因 为 每 个 师 傅 修 每 辆 车 的 代 价 不 是 为啥没办法建图?因为每个师傅修每辆车的代价不是 ?定值

不 是 定 值 , 就 想 办 法 变 成 定 值 。 不是定值,就想办法变成定值。 ,

考 虑 某 个 师 傅 一 次 修 车 a 1 , a 2 , a 3 , a 4 考虑某个师傅一次修车a_1,a_2,a_3,a_4 a1,a2,a3,a4

那 么 a 1 的 等 待 时 间 是 a 1 那么a_1的等待时间是a_1 a1a1

a 2 的 等 待 时 间 是 a 1 + a 2 a_2的等待时间是a_1+a_2 a2a1+a2

a 3 的 等 待 时 间 是 a 1 + a 2 + a 3 a_3的等待时间是a_1+a_2+a_3 a3a1+a2+a3

a 4 的 等 待 时 间 是 a 1 + a 2 + a 3 + a 4 a_4的等待时间是a_1+a_2+a_3+a_4 a4a1+a2+a3+a4

设 某 个 师 傅 修 了 x 辆 车 设某个师傅修了x辆车 x

最 后 修 的 车 的 代 价 只 需 要 在 原 来 基 础 上 乘 1 最后修的车的代价只需要在原来基础上乘1 1

倒 数 第 二 次 修 车 的 代 价 只 需 要 在 原 来 的 基 础 上 乘 2 倒数第二次修车的代价只需要在原来的基础上乘2 2

. . . . . . . . . . . . . . . . . . . . . . ...................... ......................

于 是 把 m 个 师 傅 分 成 n 层 于是把m个师傅分成n层 mn

第 i 层 表 示 修 倒 数 第 i 辆 车 的 师 傅 , 那 么 代 价 乘 以 i 第i层表示修倒数第i辆车的师傅,那么代价乘以i ii,i

每 层 的 每 个 师 傅 向 每 一 辆 车 连 边 即 可 每层的每个师傅向每一辆车连边即可

跑 最 小 费 用 最 大 流 , 对 于 每 个 师 傅 而 言 一 定 是 依 次 选 择 跑最小费用最大流,对于每个师傅而言一定是依次选择 ,

修 倒 数 第 1 辆 车 , 修 倒 数 第 2 辆 车 , 实 际 上 这 也 是 连 续 的 修倒数第1辆车,修倒数第2辆车,实际上这也是连续的 1,2,

#include 
using namespace std;
const int maxn=2e5+10;
const int inf=1e9; 
int n,m,s,t,c[509][509];
struct edge{int to,nxt,flow,w;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int w,int flow){d[++cnt]=(edge){v,head[u],flow,w},head[u]=cnt;d[++cnt]=(edge){u,head[v],0,-w},head[v]=cnt;
}
int dis[maxn],mincost,vis[maxn],pre[maxn],flow[maxn];
bool spfa()
{for(int i=0;i<=t;i++)	dis[i]=inf,vis[i]=0;dis[s]=0,flow[s]=inf;queueq; q.push( s );while( !q.empty() ){int u=q.front(); q.pop();vis[u]=0;for(int i=head[u];i;i=d[i].nxt ){int v=d[i].to;if( d[i].flow&&dis[v]>dis[u]+d[i].w ){dis[v]=dis[u]+d[i].w;flow[v]=min(flow[u],d[i].flow);pre[v]=i;if(	!vis[v] )	vis[v]=1,q.push( v );}}}return dis[t]!=inf;
}
int dinic()
{while( spfa() ){int x=t;mincost+=flow[t]*dis[t];while( x!=s ){int i=pre[x];d[i].flow-=flow[t];d[i^1].flow+=flow[t];x=d[i^1].to;}}
}
int main()
{cin >> m >> n;//m位技术人员,n位车主for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin >> c[i][j];s=0,t=n*m+n+1;for(int i=1;i<=n*m;i++)	add(s,i,0,1);//源点连向每个师傅for(int i=1;i<=m;i++)//枚举每个师傅 for(int j=1;j<=n;j++)//枚举每个车 for(int k=1;k<=n;k++)//枚举每个时刻 {int id=(k-1)*m+i;//第k层图,每层图有m个师傅add(id,j+n*m,c[j][i]*k,1);	} for(int i=1;i<=n;i++)	add(n*m+i,t,0,1);dinic();printf("%.2lf",double(mincost)/(n*1.0) );
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部