BZOJ 1070 [SCOI2007]修車 (費用流)
阿新 • • 發佈:2019-02-10
最小 倒數 sizeof queue ffffff pri getc spf truct
BZOJ 1070 [SCOI2007]修車 (費用流)
計算出每一輛車的離開的時間有些難。
可以考慮每一輛車對時間造成的貢獻。
首先把每一個工作人員拆成n個點。
重點來了:第i個點代表這個人修的車中倒數第i輛
由於我們無法確定是該人修多少輛車。
我們反過來設就沒有問題。
然後將每輛車向這些點連邊,流量為1費用為**F(i,j)*i**
源點連向車,工作人員連向匯點。
跑最小費用最大流。
/*header*/ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #include <map> #include <queue> #define gc getchar() #define pc putchar #define ll long long #define mk make_pair #define fi first #define se second using namespace std; inline int gi() { int x = 0,f = 1;char c = gc; while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;} while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f; } const int maxN = 5000 + 7; const int maxM = 100000 + 7 ; const int inf = 0x3f3f3f3f; int n,m,s,t; namespace FF { int ans,maxflow,head[maxN]; struct Node { int u,v,flow,spend,nex; } Map[maxM]; int dis[maxN],vis[maxN],num,path[maxN]; void init() { s = n * m + n + 1; t = s + 1; num = -1; memset(head,-1,sizeof(head)); return; } void add_Node(int u,int v,int w,int spend) { Map[++ num] = (Node) {u , v, w, spend, head[u]};head[u] = num; Map[++ num] = (Node) {v , u, 0, -spend, head[v]};head[v] = num; return ; } bool spfa() { queue<int>q; q.push(s); memset(dis,0x3f,sizeof(dis)); memset(path,0,sizeof(path)); dis[s] = 0; vis[s] = true; while(!q.empty()) { int p = q.front(); q.pop(); vis[p] = false; for(int i = head[p]; i != -1; i = Map[i].nex) { int v = Map[i].v; if(dis[v] > dis[p] + Map[i].spend && Map[i].flow) { dis[v] = dis[p] + Map[i].spend; path[v] = i; if(!vis[v]) { q.push(v); vis[v] = true; } } } } if(dis[t] == 0x3f3f3f3f) return false; return true; } int min(int a,int b) { return a > b ? b : a ; } void f() { int mn = 0x7fffffff; for(int i = t; i != s; i = Map[path[i]].u) mn = min(mn,Map[path[i]].flow); ans += mn; for(int i = t; i != s; i = Map[path[i]].u) { Map[path[i]].flow -= mn; Map[path[i] ^ 1].flow += mn; maxflow += mn * Map[path[i]].spend; } } void EK() { while(spfa()) f(); double anss = 1.0 * maxflow; printf("%.2lf",anss / n); return ; } } int a[100][700]; int main() { m = gi();n = gi(); FF::init(); for(int i = 1;i <= n;++ i) for(int j = 1;j <= m;++ j) a[j][i] = gi(); for(int i = 1;i <= m;++ i) { for(int j = 1;j <= n;++ j) { for(int k = 1;k <= n;++ k) { FF::add_Node(n * m + k,(i - 1) * n + j, 1,a[i][k] * j); } } } for(int i = 1;i <= n;++ i) FF::add_Node(s , n * m + i, 1, 0); for(int i = 1;i <= m;++ i) { for(int j = 1;j <= n;++ j) { FF::add_Node((i - 1) * n + j, t, 1,0); } } FF::EK(); return 0; }
BZOJ 1070 [SCOI2007]修車 (費用流)