ZOJ 3229 Shoot the Bullet-上下界网络流

题目描述

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 365
#define MAXM 1000
#define MAXC 100
#define MAXE (MAXN*2+MAXN*MAXC+MAXM*2+10)
#define INF 2000000000

struct node{
    int v,c,b;
    node *next,*back;
}edge[MAXE*2+10],*adj[MAXN+MAXM+10],*ecnt=&edge[0];

int n,m,C[MAXN+10],ans[MAXN+10][MAXC+10],s,t,ss,tt,S,T;
int tot,flow,du[MAXN+MAXM+10],d[MAXN+MAXM+10],vd[MAXN+MAXM+10],col[MAXN+10][MAXC+10];

int e[MAXN+10][MAXC+10],cnte;

void Init()
{
    tot=cnte=0;
    memset(adj,0,sizeof adj);
    ecnt=&edge[0];
    memset(du,0,sizeof du);
    memset(col,0,sizeof col);
    memset(e,0,sizeof e);
}
void addedge(int u,int v,int c,int b)
{
    node *p=++ecnt; ++cnte;
    p->v=v;
    p->c=c,p->b=b;
    p->next=adj[u],p->back=ecnt+1;
    adj[u]=p;
    p=++ecnt; ++cnte;
    p->v=u;
    p->c=0,p->b=b;
    p->next=adj[v],p->back=ecnt-1;
    adj[v]=p;
}
void limitflow(int x,int y,int b,int c)
{
    addedge(x,y,c-b,b);
    du[x]-=b,du[y]+=b;
}
void read()
{
    int x,d,l,r;
    s=1,t=n+m+2;
    for(int i=1;i<=m;i++){
        scanf("%d",&x);
        limitflow(1+n+i,t,x,INF);
    }
    for(int i=1;i<=n;i++){
        scanf("%d%d",&C[i],&d);
        limitflow(s,1+i,0,d);
        for(int j=1;j<=C[i];j++){
            scanf("%d%d%d",&x,&l,&r);
            e[i][j]=l;
            limitflow(1+i,1+n+x+1,l,r);
            col[i][j]=cnte;
        }
    }
    limitflow(t,s,0,INF);
    ss=t+1,tt=t+2;
    for(int i=s;i<=t;i++){
        if(du[i]>0) addedge(ss,i,du[i],0),tot+=du[i];
        if(du[i]<0) addedge(i,tt,-du[i],0);
    }
}
int aug(int u,int augc)
{
    int augco=augc,mind=tt,delta,v; //tt,not T
    if(u==T)
        return augc;
    for(node *p=adj[u];p;p=p->next){
        v=p->v;
        if(p->c>0){
            if(d[u]==d[v]+1){
                delta=aug(v,min(augco,p->c));
                p->c-=delta;
                p->back->c+=delta;
                augco-=delta;
                if(d[S]>=tt) //tt,not T
                    return augc-augco;
                if(!augco)
                    break;
            }
            mind=min(mind,d[v]);
        }
    }
    if(augco==augc){
        vd[d[u]]--;
        if(!vd[d[u]])
            d[S]=tt+1; //tt,not T
        d[u]=mind+1;
        vd[d[u]]++;
    }
    return augc-augco;
}
void Isap(int s0,int t0)
{
    S=s0,T=t0;
    flow=0;
    memset(d,0,sizeof d);
    memset(vd,0,sizeof vd);
    vd[0]=tt; // tt,not T,有反向边,点都还是连通的
    while(d[S]<tt) //tt not T
        flow+=aug(S,INF);
}
int main()
{
    while(scanf("%d%d",&n,&m)==2){
        Init();
        read();
        Isap(ss,tt);
        if(flow==tot){
            Isap(s,t);
            printf("%d\n",flow);
            memset(ans,0,sizeof ans);
            /*for(int i=1;i<=n;i++){
                for(node *p=adj[i+1];p;p=p->next){
                    if(p->v>=2+n&&p->v<=1+n+m)
                        ans[i][col[i][p->v-(n+1)]]=p->back->c+p->back->b;
                }
            }
            for(int i=1;i<=n;i++)
                for(int j=1;j<=C[i];j++)
                    printf("%d\n",ans[i][j]);*/
            for(int i=1;i<=n;i++)
                for(int j=1;j<=C[i];j++)
                    printf("%d\n",e[i][j]+edge[col[i][j]].c);
        }
        else
            printf("-1\n");
        puts("");
    }
}

但不知道为什么这个是错的:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 365
#define MAXM 1000
#define MAXC 100
#define MAXE (MAXN*2+MAXN*MAXC+MAXM*2+10)
#define INF 2000000000

struct node{
    int v,c,b;
    node *next,*back;
}edge[MAXE*2+10],*adj[MAXN+MAXM+10],*ecnt=&edge[0];

int n,m,C[MAXN+10],ans[MAXN+10][MAXC+10],s,t,ss,tt,S,T;
int tot,flow,du[MAXN+MAXM+10],d[MAXN+MAXM+10],vd[MAXN+MAXM+10],col[MAXN+10][MAXC+10];

void Init()
{
    tot=0;
    memset(adj,0,sizeof adj);
    ecnt=&edge[0];
    memset(du,0,sizeof du);
    memset(col,0,sizeof col);
}
void addedge(int u,int v,int c,int b)
{
    node *p=++ecnt;
    p->v=v;
    p->c=c,p->b=b;
    p->next=adj[u],p->back=ecnt+1;
    adj[u]=p;
    p=++ecnt;
    p->v=u;
    p->c=0,p->b=b;
    p->next=adj[v],p->back=ecnt-1;
    adj[v]=p;
}
void limitflow(int x,int y,int b,int c)
{
    addedge(x,y,c-b,b);
    du[x]-=b,du[y]+=b;
}
void read()
{
    int x,d,l,r;
    s=1,t=n+m+2;
    for(int i=1;i<=m;i++){
        scanf("%d",&x);
        limitflow(1+n+i,t,x,INF);
    }
    for(int i=1;i<=n;i++){
        scanf("%d%d",&C[i],&d);
        limitflow(s,1+i,0,d);
        for(int j=1;j<=C[i];j++){
            scanf("%d%d%d",&x,&l,&r);
            col[i][x+1]=j;
            limitflow(1+i,1+n+x+1,l,r);
        }
    }
    limitflow(t,s,0,INF);
    ss=t+1,tt=t+2;
    for(int i=s;i<=t;i++){
        if(du[i]>0) addedge(ss,i,du[i],0),tot+=du[i];
        if(du[i]<0) addedge(i,tt,-du[i],0);
    }
}
int aug(int u,int augc)
{
    int augco=augc,mind=tt,delta,v;
    if(u==T)
        return augc;
    for(node *p=adj[u];p;p=p->next){
        v=p->v;
        if(p->c>0){
            if(d[u]==d[v]+1){
                delta=aug(v,min(augco,p->c));
                p->c-=delta;
                p->back->c+=delta;
                augco-=delta;
                if(d[S]>=tt)
                    return augc-augco;
                if(!augco)
                    break;
            }
            mind=min(mind,d[v]);
        }
    }
    if(augco==augc){
        vd[d[u]]--;
        if(!vd[d[u]])
            d[S]=tt+1;
        d[u]=mind+1;
        vd[d[u]]++;
    }
    return augc-augco;
}
void Isap(int s0,int t0)
{
    S=s0,T=t0;
    flow=0;
    memset(d,0,sizeof d);
    memset(vd,0,sizeof vd);
    vd[0]=tt;
    while(d[S]<tt)
        flow+=aug(S,INF);
}
int main()
{
    while(scanf("%d%d",&n,&m)==2){
        Init();
        read();
        Isap(ss,tt);
        if(flow==tot){
            Isap(s,t);
            printf("%d\n",flow);
            memset(ans,0,sizeof ans);
            for(int i=1;i<=n;i++){
                for(node *p=adj[i+1];p;p=p->next){
                    if(p->v>=1+n&&p->v<=1+n+m)
                        ans[i][col[i][p->v-(n+1)]]=p->back->c+p->back->b;
                }
            }
            for(int i=1;i<=n;i++)
                for(int j=1;j<=C[i];j++)
                    printf("%d\n",ans[i][j]);
        }
        else
            printf("-1\n");
        puts("");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值