bzoj1070(修車)(費用流)
阿新 • • 發佈:2018-11-02
建圖重要。
m個工人, n輛車
源點向每輛車連一條容量為1費用為0的邊。
把每個工人拆成n個,第i個工人的第j個節點表示,第i個工人修倒數j輛車。
每輛車向這n*m個工人連一條容量為1費用為這個工人修這輛車的時間*這個工人倒數第幾個修這輛車。
因為修一輛車只會使在它後面修的都+修這輛車的時間。
//我服了,爛費用流板子,一直t,狗了一個別人的spfa,才過。我就吐槽一句,是誰教我的費用流!?
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int n, m, shi[15][65], huan, hui,tot; int tp = 1, dis[100000], vis[100000], tov[100000], tof[100000], tow[100000], h[100000], nex[100000], fa[100000], bian[100000]; double ans; deque<int> q; void read(int &x) { x = 0; int f = 0; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = 1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } if(f) x = -x; } void add(int x,int y,int w,int f) { tp++; tov[tp] = y; tow[tp] = w; tof[tp] = f; nex[tp] = h[x]; h[x] = tp; tp++; tov[tp] = x; tow[tp] = 0; tof[tp] = -f; nex[tp] = h[y]; h[y] = tp; } /*bool spfa() { memset(dis,0x3f3f3f3f,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(q,0,sizeof(q)); int head = 0, tail = 1; dis[huan] = 0; q[tail] = huan; vis[huan] = 1; while(head < tail) { head++; int x = q[head]; for(int i = h[x]; i; i = nex[i]) { tot++; int v = tov[i]; if(dis[v] > dis[x] + tof[i] && tow[i] != 0) { dis[v] = dis[x] + tof[i]; fa[v] = x; bian[v] = i; if(vis[v] == 0) { vis[v] = 1; tail++; q[tail] = v; } } } vis[x] = 0; } return dis[hui] == dis[hui+1] ? 0 : 1; } */ bool spfa(int s,int e) { memset(dis,63,sizeof(dis)); dis[s] = 0; vis[s] = 1; q.push_front(s); while(q.size()) { int f = q.front(); q.pop_front(); vis[f] = 0; for(int i = h[f];i;i = nex[i]) { int v = tov[i]; if(tow[i] && dis[v] > dis[f] + tof[i]) { dis[v] = dis[f] + tof[i]; bian[v] = i; fa[v]= f; if(!vis[v]) { vis[v] = 1; if(q.empty() || dis[v] < dis[q.front()]) q.push_front(v); else q.push_back(v); } } } } if(dis[e] == dis[e+2]) return false; return true; } int liu() { int u=hui; int delta=1e9; while(u!=huan) { delta=min(delta,tow[bian[u]]); u=fa[u]; } u=hui; while(u!=huan) { tow[bian[u]]-=delta; tow[bian[u]^1]+=delta; u=fa[u]; } return dis[hui]; } int main() { int haha = 1; read(m);read(n); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) read(shi[j][i]); } huan = 0; hui = n + m * n + 1; for(int i = 1; i <= n; i++) { add(huan, i, 1,0); } for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) for(int k = 1; k <= n; k++) add(i,n+(j-1)*n+k,1,k * shi[j][i]); } for(int i = 1; i <= m; i++) for(int j = 1; j <= n; j++) add(n+(i-1)*n + j, hui,1,0); while(spfa(huan,hui)) { ans += liu(); } printf("%0.2lf",ans/n); //cout <<tot ; return 0; }