Shoot the Bullet(ZOJ3229)(有源匯上下界最大流)

描述

ensokyo 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!node

 

 

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.ios

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

Input

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

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 <= Tm, 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.ui

Output a blank line after each case.this

Sample Inputspa

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 Outputrest

36
6
6
6
6
6
6

36
9
6
3
3
6
9

-1

題意:

大體是說一個男生要個其餘女生拍照,總共拍N天,總共有M個女生,blog

接下來一行是說M個女生,每一個女生至少要拍照的數量

而後天天都有本身的拍照計劃,給多少女生拍照,今天拍照的總數量

接下來一行是對於女生x,這一天拍照的上限L和下限R

題解:

有源匯上下界最大流,先建圖,首先源點和天天連線,上屆是這一天拍照總數,下界是0,每一天再和當天拍照的女生建邊,上下界是L,R,每一個女生和匯點建邊,上下界是INf,和給這個女生拍照的最少數量。

而後轉換爲無源匯上下界最大流,創建超級源點和匯點,跑最大流看是否滿流,是則,再跑一遍,求出最大流,否輸出-1

 

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define inf 0x3f3f3f3f
#define ll long long
#define MAXN 30000
using namespace std;
int n,m;//點數、邊數
int sp,tp;//原點、匯點
struct node
{
    int v,next;
    ll cap;
}mp[MAXN*10];
int pre[MAXN],dis[MAXN],cur[MAXN];//cur爲當前弧優化,dis存儲分層圖中每一個點的層數(即到原點的最短距離),pre建鄰接表
int cnt=0;
void init()//不要忘記初始化
{
    cnt=0;
    memset(pre,-1,sizeof(pre));
}
void add(int u,int v,int w)//加邊
{
    mp[cnt].v=v;
    mp[cnt].cap=w;
    mp[cnt].next=pre[u];
    pre[u]=cnt++;
    mp[cnt].v=u;
    mp[cnt].cap=0;
    mp[cnt].next=pre[v];
    pre[v]=cnt++;
}
bool bfs()//建分層圖
{
    memset(dis,-1,sizeof(dis));
    queue<int>q;
    while(!q.empty())
        q.pop();
    q.push(sp);
    dis[sp]=0;
    int u,v;
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        for(int i=pre[u];i!=-1;i=mp[i].next)
        {
            v=mp[i].v;
            if(dis[v]==-1&&mp[i].cap>0)
            {
                dis[v]=dis[u]+1;
                q.push(v);
                if(v==tp)
                    break;
            }
        }
    }
    return dis[tp]!=-1;
}
ll dfs(int u,ll cap)//尋找增廣路
{
    if(u==tp||cap==0)
        return cap;
    ll res=0,f;
    for(int &i=cur[u];i!=-1;i=mp[i].next)
    {
        int v=mp[i].v;
        if(dis[v]==dis[u]+1&&(f=dfs(v,min(cap-res,mp[i].cap)))>0)
        {
            mp[i].cap-=f;
            mp[i^1].cap+=f;
            res+=f;
            if(res==cap)
                return cap;
        }
    }
    if(!res)
        dis[u]=-1;
    return res;
}
ll dinic()
{
    ll ans=0;
    while(bfs())
    {
        for(int i=0;i<=tp;i++)
            cur[i]=pre[i];
        ans+=dfs(sp,inf);
    }
    return ans;
}
int d[MAXN],a[MAXN];
int g[400][1100];
int st[400][1100];
int main() {
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        memset(d,0, sizeof(d));
        int sum=0;
        int x;
        for (int i = 1; i <=m ; ++i) {
            scanf("%d",&x);
            add(n+i,n+m+1,inf);
            d[n+i]-=x;
            d[n+m+1]+=x;
        }
        int b;
        for (int i = 1; i <=n ; ++i) {
            scanf("%d%d",&a[i],&b);
            add(0,i,b);
            int l,r;
            for (int j = 0; j <a[i] ; ++j) {
                scanf("%d%d%d",&x,&l,&r);
                add(i,n+x+1,r-l);
                d[i]-=l;
                d[n+x+1]+=l;
                st[i][j]=l;
                g[i][j]=(cnt-2);
            }
        }
        add(n+m+1,0,inf);

        for (int i = 0 ; i <=n+m+1 ; ++i) {
            if(d[i]>0)
            {
                add(n+m+2,i,d[i]);
                sum+=d[i];
            }
            if(d[i]<0)
            {
                add(i,n+m+3,-d[i]);
            }
        }
        sp=n+m+2;tp=n+m+3;
        if(sum!=dinic())
        {
            printf("-1\n");
        }
        else
        {
            sp=0,tp=n+m+1;
            printf("%lld\n",dinic());
            for (int i = 1; i <=n ; ++i) {
                for (int j = 0; j <a[i] ; ++j) {
                    printf("%lld\n",mp[g[i][j]+1].cap+(ll)st[i][j]);
                }
            }

        }
        printf("\n");
    }
    return 0;
}
//zoj3229
//loj116
相關文章
相關標籤/搜索