【有源汇有上下界最大流】ZOJ-3229 Shoot the Bullet

来源:互联网 发布:linux shell 设置变量 编辑:程序博客网 时间:2024/04/30 11:13
Shoot the Bullet

Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge

Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utopia where humans and other beings such as fairies, youkai(phantoms), and gods live peacefully together. Shameimaru Aya is a crow tengu with the ability to manipulate wind who has been in Gensokyo for over 1000 years. She runs the Bunbunmaru News - a newspaper chock-full of rumors, and owns the Bunkachou - her record of interesting observations for Bunbunmaru News articles and pictures of beautiful danmaku(barrange) or cute girls living in Gensokyo. She is the biggest connoisseur of rumors about the girls of Gensokyo among the tengu. Her intelligence gathering abilities are the best in Gensokyo!

During the coming n days, Aya is planning to take many photos of m cute girls living in Gensokyo to write Bunbunmaru News daily and record at least Gx photos of girl x in total in the Bunkachou. At the k-th day, there are Ck targets, Tk1Tk2, ..., TkCk. The number of photos of target Tki that Aya takes should be in range [LkiRki], if less, Aya cannot write an interesting article, if more, the girl will become angry and use her last spell card to attack Aya. What's more, Aya cannot take more than Dk photos at the k-th day. Under these constraints, the more photos, the better.

Aya is not good at solving this complex problem. So she comes to you, an earthling, for help.

Input

There are about 40 cases. Process to the end of file.

Each case begins with two integers 1 <= n <= 365, 1 <= m <= 1000. Then m integers, G1G2, ..., Gm in range [0, 10000]. Then n days. Each day begins with two integer 1 <= C <= 100, 0 <= D <= 30000. Then C different targets. Each target is described by three integers, 0 <= T < m, 0 <= L <= R <= 100.

Output

For each case, first output the number of photos Aya can take, -1 if it's impossible to satisfy her needing. If there is a best strategy, output the number of photos of each girl Aya should take at each day on separate lines. The output must be in the same order as the input. If there are more than one best strategy, any one will be OK.

Output a blank line after each case.

Sample Input

2 312 12 123 180 3 91 3 92 3 93 180 3 91 3 92 3 92 312 12 123 180 3 91 3 92 3 93 180 0 31 3 62 6 92 312 12 123 150 3 91 3 92 3 93 210 0 31 3 62 6 12

Sample Output

3666666636963369-1
————————————————————蒟蒻的分割线————————————————————
前言:这道题花费了那么久时间,结果是因为输出格式问题WA。为什么不给PE!!
题意:题意大概是:
给定N天,有M个女孩要上报纸。每个人至少被拍Gi张照片。
每天拍照总数不超过Di。
每天要给Ci个女孩拍照,每个女孩拍照的张数限定在[L, R]内。
求最多的照片总数。
思路:
图很容易,画一画就发现 每一天、每一个女孩是顶点。所有的女孩流入汇点。源点流入每一天。
接下来是求最大流的方法。
首先添加原汇点到原源点的边INF。建立伴随网络。求一次超级源汇点的最大流。
然后保存t->s的流量。删除这条边。(设为0)。再求一次原源汇点的最大流即可。
下面简单证明一下:
设原来的源汇点为S0, T0, 超级源汇点为S', T'。
第一次跑S'到T'的最大流 其实是为了满足下界流,这个时候如果S'的每条边满载,说明下界满足了。
再跑一次S0到T0的最大流,因为删除了t->s,所以这个时候只是把残留网络中的自由流量都跑向了T0。
然后用之前的流量加上这次得到的最大增量,就是所求的最大流了。
P.S. 这道题就算不删除t->s,也不保存,直接跑两次也能过,所以怪怪的!!
代码如下:
/*ID: j.sure.1PROG:LANG: C++*//****************************************/#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <queue>#include <vector>#include <map>#include <string>#include <climits>#include <iostream>#define INF 0x3f3f3f3fusing namespace std;/****************************************/const int N = 1500, M = 1e5;struct Node {    int u, v, w;int next;} edge[M];int tot, lev[N], head[N], q[N], cur[N], s[N];int n, m, f[N], bel[500][N], sta[M];void init(){    tot = 0;    memset(head, -1, sizeof(head));    memset(f, 0, sizeof(f));    memset(bel, 0, sizeof(bel));}void add(int u, int v, int w){    edge[tot].u = u; edge[tot].v = v; edge[tot].w = w;    edge[tot].next = head[u]; head[u] = tot++;}bool bfs(int S, int T){    memset(lev, -1, sizeof(lev));    int fron = 0, rear = 0;    q[rear++] = S;lev[S] = 0;    while(fron < rear) {        int u = q[fron%N]; fron++;        for(int i = head[u]; ~i; i = edge[i].next) {            int v = edge[i].v;            if(edge[i].w && lev[v] == -1) {                lev[v] = lev[u] + 1;                q[rear%N] = v; rear++;                if(v == T) return true;            }        }    }    return false;}int Dinic(int S, int T){    int ret = 0;    while(bfs(S, T)) {        memcpy(cur, head, sizeof(head));        int u = S, top = 0;        while(1) {            if(u == T) {                int mini = INF, loc;                for(int i = 0; i < top; i++) {                    if(mini > edge[s[i]].w) {                        mini = edge[s[i]].w;                        loc = i;                    }}                for(int i = 0; i < top; i++) {                    edge[s[i]].w -= mini;                    edge[s[i]^1].w += mini;                }                ret += mini;                top = loc;                u = edge[s[top]].u;            }int &i = cur[u];            for(; ~i; i = edge[i].next) {int v = edge[i].v;                if(edge[i].w && lev[v] == lev[u] + 1) break;}            if(~i) {                s[top++] = i;                u = edge[i].v;            }            else {                if(!top) break;                lev[u] = -1;                u = edge[s[--top]].u;            }        }    }    return ret;}bool judge(int S){for(int i = head[S]; ~i; i = edge[i].next) {if(edge[i].w) return false;}return true;}void pr(){for(int u = 1; u <= n; u++) {int cnt = 0;for(int i = head[u]; ~i; i = edge[i].next) {int v = edge[i].v;if(v > n && v <= n+m) {sta[cnt++] = edge[i^1].w + bel[u][v-n];}}for(int i = cnt-1; i >= 0; i--) {printf("%d\n", sta[i]);}}}int main(){while(~scanf("%d%d", &n, &m)) {init();int Ss = 0, Tt = n+m+1;int S = n+m+2, T = n+m+3;int maxG;for(int i = 1; i <= m; i++) {scanf("%d", &maxG);add(n+i, Tt, INF-maxG); add(Tt, n+i, 0);f[n+i] -= maxG;f[Tt] += maxG;}int C, D;for(int u = 1; u <= n; u++) {scanf("%d%d", &C, &D);add(Ss, u, D); add(u, Ss, 0);int v, b, c;for(int i = 1; i <= C; i++) {scanf("%d%d%d", &v, &b, &c);bel[u][v+1] = b;v += (n+1);add(u, v, c-b); add(v, u, 0);f[u] -= b;f[v] += b;}}for(int i = 0; i <= Tt; i++) {if(f[i] > 0) {add(S, i, f[i]); add(i, S, 0);}else if(f[i] < 0) {add(i, T, -f[i]); add(T, i, 0);}}add(Tt, Ss, INF); add(Ss, Tt, 0);int ret = Dinic(S, T);if(!judge(S)) {puts("-1\n");continue;}int cur = edge[tot-1].w; edge[tot-1].w = 0;int ans = Dinic(Ss, Tt);ans += cur;printf("%d\n", ans);pr();puts("");}return 0;}


0 0