收藏:http://www.tuicool.com/articles/QRr2Qb
把每一天看成一个点,每个女孩也看成一个点,增加源和汇s、t,源向每一天连上[0,d]的边,每一天与每个女孩如果有拍照任务的话连上[l,r]的边,
每个女孩与汇连上[g,oo]的边,于是构成一个有上下界的图。
所以这道题目我们可以转换一下,只要连一条T → S的边,流量为无穷,没有下界,那么原图就得到一个无源汇的循环流图。
接下来的事情一样:原图中的边的流量设成自由流量ci – bi。新建源点SS汇点TT,求Mi,连边。然后求SS → TT最大流,判是否满流。
view code#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <vector> using namespace std; typedef long long ll; const int INF = 1<<30; const int N = 1500; const int M = 1e6; int n, m, pre[N], d[N], cur[N], s, t, ss, tt; int dis[N], in[N], low[36666], lcnt; bool vis[N]; struct edge { int u, v, cap, next; edge() {} edge(int u, int v, int c, int next):u(u),v(v),cap(c),next(next) {} }e[M]; int ecnt; void addedge(int u, int v, int w) { e[ecnt] = edge(u, v, w, pre[u]); pre[u] = ecnt++; e[ecnt] = edge(v, u, 0, pre[v]); pre[v] = ecnt++; } bool BFS(int s, int t) { memset(vis, 0, sizeof(vis)); queue<int >q; q.push(s); vis[s] = 1; d[s] = 0; while(!q.empty()) { int x = q.front(); q.pop(); for(int i=pre[x]; ~i; i=e[i].next) { int v = e[i].v; if(!vis[v] && e[i].cap>0) { vis[v] = 1; d[v] = d[x] + 1; q.push(v); } } } return vis[t]; } ll DFS(int x, ll c, int s, int t) { if(x==t || c==0) return c; ll flow = 0, f; for(int &i = cur[x]; ~i; i = e[i].next) { int v = e[i].v; if(d[v] == d[x]+1 && (f=DFS(v, min(c, (ll)e[i].cap), s, t))>0) { e[i].cap -= f; e[i^1].cap += f; flow += f; c -= f; if(c==0) break; } } return flow; } ll Maxflow(int s, int t) { ll flow = 0; while(BFS(s, t)) { memcpy(cur, pre, sizeof(pre)); flow += DFS(s, INF, s, t); } return flow; } int main() { // freopen("in.txt", "r", stdin); while(scanf("%d%d", &n, &m)>0) { ll sum = 0; int g, id, R, k; s = 0, t = m+n+1; ss = n+m+2, tt = m+n+3; memset(pre, -1, sizeof(pre)); memset(in, 0, sizeof(in)); ecnt = 0, lcnt = 0; for(int i=1; i<=m; i++) { scanf("%d", &g); in[i+n] -= g; in[t] += g; } for(int i=1; i<=n; i++) { scanf("%d%d", &k, &dis[i]); for(int j=0; j<k; j++) { scanf("%d%d%d", &id, &low[++lcnt], &R); addedge(i, id+n+1, R-low[lcnt]); in[i] -= low[lcnt]; in[id+n+1] += low[lcnt]; } } for(int i= 1; i<=n; i++) addedge(s, i, dis[i]); for(int i= 1; i<=m; i++) addedge(i+n, t, INF); addedge(t, s, INF); for(int i = s; i<=t; i++) { if(in[i]>0) addedge(ss, i, in[i]), sum += in[i]; if(in[i]<0) addedge(i, tt, -in[i]); } if(Maxflow(ss, tt)==sum) { Maxflow(s, t); addedge(t, s, -INF); int ans = 0; for(int i = pre[0]; ~i; i=e[i].next) { ans += e[i^1].cap ; // printf("u = %d, cap = %d ", e[i^1].u, e[i^1].cap); } printf("%d ", ans); for(int i=1; i<=lcnt; i++) printf("%d ", e[2*i-1].cap+low[i]); } else puts("-1"); puts(""); } return 0; }