博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1070 [SCOI2007]修车 最小费用最大流
阅读量:5307 次
发布时间:2019-06-14

本文共 5932 字,大约阅读时间需要 19 分钟。

构造一个图,左边nmn∗m个点,表示第jj个技术人员修的倒数第ii辆车,右边nn个点,表示第kk辆车

  源点向左边的点连(w=1,cost=0)(w=1,cost=0)的边,因为每个人同一时刻只能修一辆车

  左边mnm∗n个点再分别向右边nn个点连边,左边第(i,j)(i,j)个点向右边第kk个点连(w=INF,cost=it[i][j])(w=INF,cost=i∗t[i][j])的边

  相当于此时有ii个人在等待着这辆车修完,代价就是等待的人数∗修这辆车的时间

  右边的点向汇点连(w=1,cost=0)(w=1,cost=0)的边,表示每辆车只能被一个人修

  容易看出,此时最大流一定是nn,每一条w=1w=1的流表示第jj个人修的倒数第ii辆车是第kk辆车

  那么最小费用除以nn就是我们的答案

 

我写的代码一直TLE....

本地过了就是过了,OJ上TLE是OJ有问题

#include 
using namespace std;const int MAXN = 10000;const int MAXM = 100000;const int INF = 0x3f3f3f3f;struct Edge{ int to,next,cap,flow,cost;} edge[MAXM];int head[MAXN],tol;int pre[MAXN],dis[MAXN];bool vis[MAXN];int N;void init(){ tol = 0; memset(head, - 1,sizeof(head));}void addedge(int u,int v,int cap,int cost){ edge[tol].to = v; edge[tol].cap = cap; edge[tol].cost = cost; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = 0; edge[tol].cost = - cost; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++;}bool spfa(int s,int t){ queue
q; memset(dis,INF,sizeof(dis)); memset(vis,false,sizeof(vis)); memset(pre,-1,sizeof(pre)); dis[s] = 0; vis[s] = true; q.push(s); while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = false; for(int i = head[u]; i != - 1; i = edge[i].next){ int v = edge[i].to; if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ){ dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]){ vis[v] = true; q.push(v); } } } } if(pre[t] == - 1) return false; else return true;}int minCostMaxflow(int s,int t,int &cost){ int flow = 0; cost = 0; while(spfa(s,t)){ int Min = INF; for(int i = pre[t]; i != - 1; i = pre[edge[i^1].to]){ if(Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; } for(int i = pre[t]; i != - 1; i = pre[edge[i^1].to]){ edge[i].flow += Min; edge[i^1].flow -= Min; cost += edge[i].cost * Min; } flow += Min; } return cost;}int n,m;int car[70][70],id_man[70][70],id_car[70];int cnt,s,t;int main(){ cnt = 0; scanf("%d%d",&m,&n); for (int i = 1;i <= n;++i){ for (int j = 1;j <= m;++j){ scanf("%d",&car[i][j]); } } init(); s = cnt++;t = cnt++; for (int i = 1;i <= m;++i){ for (int j = 1;j <= n;++j){ addedge(s,id_man[i][j] = cnt++,1,0); } } for (int i = 1;i <= n;++i){ addedge(id_car[i] = cnt++,t,1,0); } for (int i = 1;i <= m;++i){
//第i个人 for (int j = 1;j <= n;++j){
//倒数第j次 for (int k = 1;k <= n;++k){
//车k addedge(id_man[i][j],id_car[k],1,j*car[k][i]); } } } N = cnt; int cost = 0; printf("%.2f\n",(double)minCostMaxflow(s,t,cost)/n);}

 

下面是别人的AC代码

#include 
#include
#include
#include
using namespace std;const int N = 10 + 5;const int M = 60 + 5;const int INF = 0x3f3f3f3f;int n, m;int S, T, cnt;int C[N][M], id1[N][M], id2[M];int head[N * M], len;struct nodeLib { int to, nxt, val, flow; inline void add(int a, int b, int c, int d) { to = b, val = d, flow = c; nxt = head[a], head[a] = len++; }} lib[N * M * M << 1];inline int read() { char ch; int ans = 0, neg = 1; while (ch = getchar(), ch < '0' || ch > '9') if (ch == '-') neg = -1; while (ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar(); return ans * neg;}inline void makePath(int a, int b, int c, int d) { lib[len].add(a, b, c, d); lib[len].add(b, a, 0, -d);}void init() { n = read(), m = read(); len = 2, S = ++cnt, T = ++cnt; for (int j = 1; j <= m; j++) for (int i = 1; i <= n; i++) C[i][j] = read(); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) makePath(S, id1[i][j] = ++cnt, 1, 0); for (int i = 1; i <= m; i++) makePath(id2[i] = ++cnt, T, 1, 0); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) for (int k = 1; k <= m; k++) makePath(id1[i][j], id2[k], 1, j * C[i][k]);}queue
Q;bool inQ[N * M];int dist[N * M], preE[N * M], preV[N * M];bool SPFA() { memset(dist, 0x3f, sizeof(dist)); dist[S] = 0, Q.push(S), inQ[S] = true; while (!Q.empty()) { int tmp = Q.front(); Q.pop(), inQ[tmp] = false; for (int p = head[tmp]; p; p = lib[p].nxt) { int now = lib[p].to, val = lib[p].val; if (lib[p].flow && dist[now] > dist[tmp] + val) { dist[now] = dist[tmp] + val; preE[now] = p, preV[now] = tmp; if (!inQ[now]) Q.push(now), inQ[now] = true; } } } return dist[T] != INF;}int MCMF() { int ans = 0; while (SPFA()) { int maxf = INF; for (int p = T; p != S; p = preV[p]) maxf = min(maxf, lib[preE[p]].flow); for (int p = T; p != S; p = preV[p]) lib[preE[p]].flow -= maxf, lib[preE[p] ^ 1].flow += maxf; ans += dist[T] * maxf; } return ans;}int main() { init(); printf("%.2lf\n", (double)MCMF() / m); return 0;}

 

转载于:https://www.cnblogs.com/mizersy/p/9548419.html

你可能感兴趣的文章
xml.exist() 实例演示
查看>>
判断是否为空然后赋值
查看>>
zabbix监控日志文件
查看>>
正则表达式
查看>>
pip install torch on windows, and the 'from torch._C import * ImportError: DLL load failed:' s...
查看>>
环套树
查看>>
java基础(一):我对java的三个环境变量的简单理解和配置
查看>>
arcgis api 4.x for js 结合 Echarts4 实现散点图效果(附源码下载)
查看>>
YTU 2625: B 构造函数和析构函数
查看>>
apache自带压力测试工具ab的使用及解析
查看>>
C#使用Xamarin开发可移植移动应用(2.Xamarin.Forms布局,本篇很长,注意)附源码
查看>>
jenkins搭建
查看>>
C#中使用Split分隔字符串的技巧
查看>>
eclipse的调试方法的简单介绍
查看>>
加固linux
查看>>
IPSP问题
查看>>
HNU 10362 A+B for Input-Output Practice (II)
查看>>
10.17动手动脑
查看>>
WPF中Image显示本地图片
查看>>
Windows Phone 7你不知道的8件事
查看>>