费用流写起来怪怪的
就是感觉特别暴力 估计学一下势优化能快一点qwq
题意:
给定n个任务和m个机器 每一台机器加工指定的物品需要一定的时间
问n件物品加工所需最短时间
Solution:
这个题一看是没有办法贪心的
dp的话样例就否决了
最小割没法转
所以考虑跑一个费用流
建图就非常简单 每个物品每个点每个时间全分开 n^3边 n^2点建分层图就可以了
-----Update on 11.27-------
重新看了一遍题发现好像没有之前想的那么水...
n^2点指的是n件物品 m*n表示m时间做了n工作
然后之前对于每个物品统计时间 变成第a[i][j]这个时间被用了多少次
至于点坐标反过来就行 也就是代码里面的k表示是倒数第k件
由于spfa显然不会有空的...
极限的时间复杂度是n^5 但是这个上界非常松 甚至达不到n^4 所以时间没什么压力
----------------------------------
反正n<=50 而且图肯定流的非常少
(就是数组稍微开大点)
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<queue> 6 #define ms(a,b) memset(a,b,sizeof a) 7 #define rep(i,a,n) for(int i = a;i <= n;i++) 8 #define per(i,n,a) for(int i = n;i >= a;i--) 9 #define inf 2147483647 10 using namespace std; 11 typedef long long ll; 12 typedef double D; 13 #define eps 1e-8 14 ll read() { 15 ll as = 0,fu = 1; 16 char c = getchar(); 17 while(c < '0' || c > '9') { 18 if(c == '-') fu = -1; 19 c = getchar(); 20 } 21 while(c >= '0' && c <= '9') { 22 as = as * 10 + c - '0'; 23 c = getchar(); 24 } 25 return as * fu; 26 } 27 const int N = 4005; 28 const int M = 400003; 29 //head 30 int s = N-1,t = N-2; 31 int head[N],nxt[M],mo[M],cnt = 1; 32 ll cst[M],flw[M]; 33 void _add(int x,int y,ll w,ll f) { 34 nxt[++cnt] = head[x]; 35 head[x] = cnt; 36 mo[cnt] = y,cst[cnt] = w,flw[cnt] = f; 37 } 38 void add(int x,int y,ll w,ll f) { 39 if(x^y) _add(x,y,w,f),_add(y,x,-w,0); 40 } 41 42 ll dis[N],flow[N]; 43 bool vis[N]; 44 int pre[N],lst[N]; 45 bool spfa() { 46 queue<int> q; 47 ms(dis,60),ms(flow,60),ms(vis,0); 48 q.push(s),dis[s] = 0,vis[s] = 1; 49 pre[t] = 0; 50 while(!q.empty()) { 51 int x = q.front(); 52 q.pop(),vis[x] = 0; 53 for(int i = head[x];i;i = nxt[i]) { 54 int sn = mo[i]; 55 if(dis[sn] > dis[x] + cst[i] && flw[i]) { 56 dis[sn] = dis[x] + cst[i]; 57 pre[sn] = x,lst[sn] = i; 58 flow[sn] = min(flow[x],flw[i]); 59 if(!vis[sn]) q.push(sn),vis[sn] = 1; 60 } 61 } 62 } 63 64 return pre[t]; 65 } 66 67 ll maxx,minn; 68 void MCMF() { 69 maxx = 0,minn = 0; 70 while(spfa()) { 71 int x = t; 72 maxx += flow[t],minn += flow[t] * dis[t]; 73 while(x ^ s) { 74 flw[lst[x]] -= flow[t]; 75 flw[lst[x] ^ 1] += flow[t]; 76 x = pre[x]; 77 } 78 } 79 } 80 int n,m; 81 int a[55][55]; 82 void solve() { 83 ms(head,0),cnt = 1; 84 n = read(),m = read(); 85 rep(i,1,n) rep(j,1,m) a[i][j] = read(); 86 rep(i,1,n) add(s,i,0,1); 87 rep(i,n+1,n+n*m) add(i,t,0,1); 88 rep(i,1,n) rep(j,1,m) rep(k,1,n) { 89 add(i,j*n+k,k * a[i][j],1); 90 } 91 MCMF(); 92 printf("%.6lf ",minn * 1.0 / (D)n); 93 } 94 95 int main() { 96 int T = read(); 97 while(T--) solve(); 98 return 0; 99 }