ZOJ 3229 Shoot the Bullet 无源汇上下界最大流

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 inGensokyo. 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 theBunkachou. 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 3
12 12 12
3 18
0 3 9
1 3 9
2 3 9
3 18
0 3 9
1 3 9
2 3 9

2 3
12 12 12
3 18
0 3 9
1 3 9
2 3 9
3 18
0 0 3
1 3 6
2 6 9

2 3
12 12 12
3 15
0 3 9
1 3 9
2 3 9
3 21
0 0 3
1 3 6
2 6 12

Sample Output

36
6
6
6
6
6
6

36
9
6
3
3
6
9

-1

External Links

Wikipedia

Touhou Wiki

把每一天看成一个点,每个女孩也看成一个点,增加源和汇,源向每一天连上[0,d]的边,每一天与每个女孩如果有拍照任务的话连上[l,c]的边,每个女孩与汇连上[g,oo]的边,于是构成一个有上下界的图,直接用上下界最大流来搞就行了

#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>

using namespace std;

#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define CLR(vis,pos) memset(vis,pos,sizeof(vis))
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LINF 1000000000000000000LL
#define eps 1e-8

typedef long long ll;

const int MAXN=2222;

struct Edge{
    int from,to,cap,flow;
};
bool cmp(const Edge& a,const Edge& b){
    return a.from < b.from || (a.from == b.from && a.to < b.to);
}
struct Dinic{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[MAXN];
    bool vis[MAXN];
    int d[MAXN];
    int cur[MAXN];
    void init(int n){
        this->n=n;
        for(int i=0;i<=n;i++)G[i].clear();
        edges.clear();
    }
    void AddEdge(int from,int to,int cap){
        edges.push_back((Edge){from,to,cap,0});
        edges.push_back((Edge){to,from,0,0});//当是无向图时,反向边容量也是cap,有向边时,反向边容量是0
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    bool BFS(){
        CLR(vis,0);
        queue<int> Q;
        Q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!Q.empty()){
            int x=Q.front();
            Q.pop();
            for(int i=0;i<G[x].size();i++){
                Edge& e=edges[G[x][i]];
                if(!vis[e.to]&&e.cap>e.flow){
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int DFS(int x,int a){
        if(x==t||a==0)return a;
        int flow=0,f;
        for(int& i=cur[x];i<G[x].size();i++){
            Edge& e=edges[G[x][i]];
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
                e.flow+=f;
                edges[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0)break;
            }
        }
        return flow;
    }
    //当所求流量大于need时就退出,降低时间
    int Maxflow(int s,int t,int need){
        this->s=s;this->t=t;
        int flow=0;
        while(BFS()){
            CLR(cur,0);
            flow+=DFS(s,INF);
            if(flow>need)return flow;
        }
        return flow;
    }
    //最小割割边
    vector<int> Mincut(){
        BFS();
        vector<int> ans;
        for(int i=0;i<edges.size();i++){
            Edge& e=edges[i];
            if(vis[e.from]&&!vis[e.to]&&e.cap>0)ans.push_back(i);
        }
        return ans;
    }
    void Reduce(){
        for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
    }
    void ClearFlow(){
        for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
    }
};

int w[MAXN],d[MAXN],low[100010];

Dinic solver;

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        solver.init(n+m+3);
        int tmp;
        CLR(w,0),CLR(d,0),CLR(low,0);
        FOR(i,1,m){
            scanf("%d",&tmp);
            w[n+i]-=tmp;
            w[n+m+1]+=tmp;
        }
        int c;
        int g=0;
        FOR(i,1,n){
            scanf("%d%d",&c,&d[i]);
            int t;
            REP(j,c){
                scanf("%d%d%d",&t,&low[++g],&tmp);
                t++;
                solver.AddEdge(i,t+n,tmp-low[g]);
                w[i]-=low[g];
                w[t+n]+=low[g];
            }
        }
        FOR(i,1,n) solver.AddEdge(0,i,d[i]);
        FOR(i,1,m) solver.AddEdge(n+i,n+m+1,INF);
        solver.AddEdge(n+m+1,0,INF);
        int sum=0;
        FOR(i,0,n+m+1){
            if(w[i]>0){
                solver.AddEdge(n+m+2,i,w[i]);
                sum+=w[i];
            }
            if(w[i]<0)
                solver.AddEdge(i,n+m+3,-w[i]);
        }
        int ans=solver.Maxflow(n+m+2,n+m+3,2*INF);
        //cout<<sum<<" "<<ans<<endl;
        if(ans!=sum){
            printf("-1\n");
        }
        else{
            tmp=solver.Maxflow(0,n+m+1,INF);
            cout<<tmp<<endl;
            FOR(i,1,g)
             printf("%d\n",solver.edges[2*i-2].flow+low[i]);
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-10-12 15:48:09

ZOJ 3229 Shoot the Bullet 无源汇上下界最大流的相关文章

[zoj] 3229 Shoot the Bullet || 有源汇上下界最大流

zoj 文文要给幻想乡的女孩子们拍照,一共n天,m个女孩子,每天文文至多拍D[i]张照片,每个女孩子总共要被文文至少拍G[i]次.在第i天,文文可以拍c[i]个女孩子,c[i]个女孩子中每个女孩子在当天被拍的次数是[l,r],求最多可以拍多少张照片,以及每天每个可以拍的女孩子被拍了多少张照片. 有源汇上下界最大流. 先跑有源汇上下界可行流,判断是否可行,若可行则此时跑原图中s到t的最大流即为答案. //代码与题解不符-- #include<cstdio> #include<algorit

zoj 2314 Reactor Cooling (无源汇上下界可行流)

Reactor Coolinghttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge The terrorist group leaded by a well known international terrorist Ben Bladen is buliding a nuclear re

ZOJ--2314--Reactor Cooling【无源汇上下界可行流】

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题意:某恐怖组织要建立一个核反应堆,他们需要设计一个冷却系统,n个点由m个管子连接,为使液体循环流动,每个节点的总流入量需要等于总流出量,现告诉你每根管子的最小流量及最大流量及它们连接的两点(有向),问是否存在可行流,如存在,输出每个管子的流量. 有上下界的网络流分为四种:无源汇的上下界可行流.有源汇的上下界可行流.有源汇的上下界最大流.有源汇的上下界最小流,这道

hdu 4940 Destroy Transportation system (无源汇上下界可行流)

Destroy Transportation system Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)http://acm.hdu.edu.cn/showproblem.php?pid=4940 Problem Description Tom is a commander, his task is destroying his enemy’s transportatio

ZOJ Problem Set - 3229 Shoot the Bullet 【有上下界网络流+流量输出】

题目:ZOJ Problem Set - 3229 Shoot the Bullet 分类:有源有汇有上下界网络流 题意:有 n 天和 m 个girls,然后每天给一部分girls拍照,每个girls 有拍照的下限,即最少要拍这么多张,然后每天有k个女孩拍照,摄影师最多可以拍num张,然后 k 个女该每天拍照数量值有上下限,然后问你有没有满足这样条件的给女孩拍照的最大方案,然后按照输入输出每天给女孩拍照的张数. 做这道题目推荐先做:这儿 分析:首先它让你判断能不能满足条件. 按照题目给出的条件很

ZOJ 2314 Reactor Cooling(无源汇上下界网络流)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2314 题意: 给出每条边流量的上下界,问是否存在可行流,如果存在则输出. 思路:先定义D(u)为顶点u发出的所有弧的流量下界与进入顶点u的所有弧的流量下界和之差(out[u]-in[u]). 对于无源汇的网络流来说: (1)新增两个顶点S(附加源点)和T(附加汇点). (2)对原网络中每个顶点u,计算出D(u),如果D(u)>0,则增加一条新弧<u,T>,这条弧的

有源汇上下界可行流(POJ2396)

题意:给出一个n*m的矩阵的每行和及每列和,还有一些格子的限制,求一组合法方案. 源点向行,汇点向列,连一条上下界均为和的边. 对于某格的限制,从它所在行向所在列连其上下界的边. 求有源汇上下界可行流即可. 具体做法可以从汇点向源点连容量为正无穷的边,转成无源汇上下界可行流. 然后可以新建超级源汇,对于一条下界为l,上界为r的边(x,y),从超级源点向y,x向超级汇点连容量为l的边,x向y连容量为r-l的边. 如果那些容量为l的边没满流,则无解. #include <cstdio> #incl

poj2396有源汇上下界可行流

题意:给一些约束条件,要求算能否有可行流,ps:刚开始输入的是每一列和,那么就建一条上下界相同的边,这样满流的时候就一定能保证流量相同了,还有0是该列(行)对另一行每个点都要满足约束条件 解法:先按无源汇上下界可行流建边,然后添加一条从t到s的容量为inf的边,从超级源到超级汇跑一边最大流,看流量是不是等于新加边的流量和,注意这题有可能输入的数据会有锚段,那么我们需要特判一下是否有矛盾出现 还要注意的一点是:我刚开始是用string+cin读入的字符,但是出现了问题,导致我代码下面的那组数据不能

ZOJ 3229 Shoot the Bullet(有源汇有上下界的最大流)

ZOJ 3229 Shoot the Bullet 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229 题意:一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝最多给C个女神拍照,每天拍照数不能超过D张,而且给每个女神 i 拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能超过Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照:否则输出-1. 思路: 有源汇有上下界的最大流 1. 在原先